26 ms·
JsonLogic
- joshlemer 5y agoA lot of shallow, smug snark coming into the comments section from people who know what s-expressions are and I guess want to brag about that for some reason. S expressions are cool but that's just _a syntax_, there are other possible syntaxes for expressions, and it's perfectly fine that somebody chooses to embed a language in JSON rather than s-expressions. Everyone suggesting to use Scheme or Clojure or Common Lisp and dropping the meme-quote that everyone eventually reimplements Lisp are missing the fact that this language is designed to be evaluated deterministically, so it does not support looping or functions and is Turing-Incomplete, unlike Clojure/Scheme/CommonLisp.
- yongjik 5y agoI think comparison to s-expressions are a red herring. In Lisp, I guess, s-expressions are an integral part of how you code. As a piece of general code, it can be great or terrible. This "JsonLogic" thing is explicitly intended to be "logic-inside-configuration" because (I hope) nobody's writing program with JsonLogic. Unfortunately, logic inside configuration is almost always a bad idea. (It doesn't matter whether you're using json or xml or s-expressions.)
- brundolf 5y agoDon't most of the problems with "logic-inside-configuration" come from turing-completeness? This spec has neither control-flow nor reusable functions (recursion); it's nothing but simple expressions. That seems safe to me.
- whalesalad 5y agoUltimately it’s all data. The difference between this and lisp is just a bunch of extra characters and noise in the stream. What is really the meaningful difference between this and an s-expression language? “” and {}, really. It’s a different way to serialize the same thing. So I’d argue a lot of the criticism is valid. We do, as an industry, tend to run in circles.
- sebmellen 5y agoThe most important difference to me is that this is usable within already extant JSON Schemas that can be patched up or added to.
- pydry 5y ago>What is really the meaningful difference between this and an s-expression language? Turing completeness. >So I’d argue a lot of the criticism is valid. I'd argue they should have paid more attention in college. This is far from a superficial difference. You might as well call HTML a programming language. Seriously.
- rvense 5y ago>>What is really the meaningful difference between this and an s-expression language? >Turing completeness. S-expressions in and of themselves are obviously not Turing complete. This language could easily have been encoded in S-expressions, just like Lisp can be encoded as JSON. (Like, trivially, as lists with quoted strings instead of atoms, or using whatever object-based syntax.)
- pydry 5y agoWell, the most famous example most definitely is. There's thousands of ways this could have been encoded. Why that one specifically?
- remram 5y agoCorrect me if I'm wrong, but not every s-expression language is Turing-complete, you need the ability to define functions which is not a given. This project doesn't have functions (or loops) seemingly on purpose (and their addition would make this weird language just as Turing-complete).
- deleted 5y ago[deleted]
- deleted 5y ago
- tgbugs 5y agoThey may be shallow comments, but they have a point. JSON is fundamentally unsuitable for anything numerical for a variety of reasons [0]. Thus, it actually can't ever even get to the point of being a suitable replacement for expressions in the languages you listed. Most web tech has insidious anti-intellectual designed baked in, and the end result is that people end up rolling their own mutually incompatible bespoke solutions to problems that were solved before the web was even a glimmer in the eyes of the advertising industry. 0. https://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript https://stackoverflow.com/questions/1423081/json-left-out-in...
- shawnz 5y agoWith s-expressions where that functionality is simply not provided as part of the underlying syntax at all, then every solution is a mutually incompatible bespoke solution. You could just use all string values in JSON and get the same effect.
- ironmagma 5y ago> Most web tech has insidious anti-intellectual designed baked in Citation? I don’t know many people who would call Brendan Eich anti-intellectual for instance.
- eevilspock 5y agoHere's the thing: I implemented exactly this for a side project where I needed users to be able to express simple logic for custom data handling rules. Here are some examples: level = new Expression(['map', ['char', ['tail', 2], 0], {'=': 1, '-': 2}]) body = new Expression(['parse', ['trim', ['body']]]) name = new Expression(['replace', ['trim', ['body', 1]], /[ \t\r\n]+/, ' ']) target = new Expression(['first', ['body', 2], ['body', 3], '']) The arg to `new Expression` is a Javascript object (i.e. can be sourced from JSON). The first element in each nested array is a function name/operator. It was absolutely trivial to implement. All the functions are implemented in a few lines of code within cases of a switch statement, and nested expressions are handled recursively. For me this is just a temporary throwaway solution while I work on other more critical stuff first. I will replace it with an s-expression based DSL later. Like JSONLogic, it won't be Turing complete. It just seems to me that JSONLogic is making a huge deal for what's really just a small reusable library.
- karmakaze 5y agoI was all set to not like this. Without even getting into the depths of it I can tell I misjudged it from the name. > JsonLogic has no setters, no loops, no functions or gotos. One rule leads to one decision, with no side effects and deterministic computation time. It's like eBPF for applications! The fact that it use JSON instead of your favorite serialization format isn't the thing to be talking about.
- millerm 5y agoSeems like a really silly lisp with string operators and is incredibly hard to read when not trivial. This will probably be the first and last time I ever ask this question, but why not just use something like clojurescript?
- eevilspock 5y agoThank you. I'm going to take a look at this for the project I mentioned in my other comment.
- sebmellen 5y agoI’m trying to define a matrix for the conditions under which a given “credential” can be accepted/is valid. The goal is to embed that matrix within the credential schema itself, such that it’s almost self-verifying, depending on the context of the credential’s usage/presentation. (A bit hard to explain without diagrams.) Using JSON to do this would allow schema portability throughout the different languages in our stack, but of course it’s an imperfect solution. Open to hearing any other options (I have looked into YAML as well but that’s a whole other ball of wax)...
- mixedCase 5y agoS-expressions do all of this, which is why everyone is suggesting you've reinvented Lisp. They're trivial to parse and easier to read than JSON for this use case.
- sebmellen 5y agoThe problem with s-expressions is that you can’t include them within an already extant JSON schema.
- mixedCase 5y agoYes you can, simply as a string. Here's your parsingMatrix from your other comment: { "if":[ { "or":[ { "===":[ { "var":"credentialData.rapidSarsCov2PCRTest.testResult" }, "negative" ] }, { "===":[ { "var":"credentialData.covid19Vaccination.hasVaccination" }, true ] } ] }, "valid", "invalid" ] } Here it is rewritten in a way more similar to how a human writes Lisp: { "if": [{"or": [{"===":[{ "var":"credentialData.rapidSarsCov2PCRTest.testResult" }, "negative" ]}, {"===":[{ "var":"credentialData.covid19Vaccination.hasVaccination" }, true ]}]}, "valid", "invalid"]}; Here it is as an s-expression, which you can store in a string: (if (or (= (var "credentialData.rapidSarsCov2PCRTest.testResult") "negative") (= (var "credentialData.covid19Vaccination.hasVaccination") #t)) "valid" "invalid") But, if you really have an intense hatred for adding an additional parsing step on top of the JSON, you can still improve over JsonLogic with just JSON primitives used in a cleaner way that more directly represents that s-expression. ["if", ["or", ["=", ["var", "credentialData.rapidSarsCov2PCRTest.testResult"], "negative"], ["=", ["var", "credentialData.covid19Vaccination.hasVaccination"], true]], "valid", "invalid"] It's still uglier than s-expressions where you can tell symbols and strings apart with more ease, but without all the syntactical noise of JSON objects combined with arrays.
- eevilspock 5y agoEssentially JSON s-expressions. I'm doing something similar in a side-project of mine as a temporary stop-gap to avoid writing (or generating) a parser for a proper s-expression syntax.
- ktpsns 5y agoAnd this is how LISP is invented. Any sufficiently complicated program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp. (Greenspun's tenth rule)
- adamkl 5y agoHere’s some great instructions on how to use JSON to do just that: https://stopa.io/post/265 https://stopa.io/post/265
- joshlemer 5y agoAre there any competing dialects of Lisp which have deterministic runtime? If people are reimplementing half of Common Lisp, then they are not implementing something that competes with this project because their language is probably turing complete. From the JsonLogic website: > JsonLogic has no setters, no loops, no functions or gotos. One rule leads to one decision, with no side effects and deterministic computation time.
- deleted 5y ago[deleted]
- pydry 5y agoIt's Turing incomplete. Like HTML. LISP is, on the other hand, a programming language. It's rather famous for it.
- mbrodersen 5y agoI have been programming for 40+ years and have never ever seen this in practice. And I am the kind of guy who have implemented my own Lisp more than once. Just for fun. However I would never use it in my day job.
- code-is-code 5y agoI also did this some year ago. A big learning was that you should define the allowed input types in the logic object. https://github.com/pubkey/secure-json-logic#readme https://github.com/pubkey/secure-json-logic#readme
- sebmellen 5y agoThanks for the input. I submitted this because I’m looking around for ways to define a matrix for accepting a given “credential” within the schema of the credential itself — a bit hard to explain without getting into it. This is the best model I’ve found so far to do what I’m trying to do, but it’s still very imperfect.
- IshKebab 5y agoHa they heard of "truthy" and "false" but apparently stopped reading before "... are a really really terrible idea!".
- mcphage 5y agoWhat's terrible about truthy and falsy? How do you even have a language without a definition of what is truthy and what is falsy?
- coldtea 5y agoThere are several languages that only allow booleans in such comparisons. There you can't do e.g. a bare: if (a) for things that e.g. in C/Java etc would be "truphy" (like 0, null, etc). Instead you need to do: if (a != null) (that is, check with an expression that returns an actual boolean true or false, not anything truthy/falsy that "coerces" to true/false). In the same way, where in Python you'd do: a = "" if not a: print "this will be printed" there you'd do it like: if not (a == "") -- or if not a.isEmpty(): ... or some such.
- mcphage 5y agoSure, but then "truthy" for that language is just true, and "falsy" is just false. It's still relevant to understand the concept of "what is considered true, and what is considered false", even if the answer is simple for certain langauges.
- coldtea 5y ago>Sure, but then "truthy" for that language is just true, and "falsy" is just false. Sure, but this stretches the meaning of "truphy" and "falsy", which was invented to describe the extra coercions to true/false. A language only allowing explicit true and false just has a concept of true and false, not of truthy and falsy.
- 5y ago
- telekid 5y agoThat's a strange lisp... A few other strategies for solving this problem include something along the lines of the Small Clojure Interpreter (1) and Defunctionalization (2, 3) [1] https://github.com/borkdude/sci https://github.com/borkdude/sci [2] https://blog.sigplan.org/2019/12/30/defunctionalization-everybody-does-it-nobody-talks-about-it/ https://blog.sigplan.org/2019/12/30/defunctionalization-ever... [3] https://www.cis.upenn.edu/~plclub/blog/2020-05-15-Defunctionalize-the-Continuation/ https://www.cis.upenn.edu/~plclub/blog/2020-05-15-Defunction...
- joshlemer 5y agoThe difference between this and a full lisp like Clojure is that this must be turing-incomplete. From the description: >JsonLogic has no setters, no loops, no functions or gotos. One rule leads to one decision, with no side effects and deterministic computation time. Also it appears that sci is still experimental: "Experimental. Breaking changes are expected to happen at this phase. "
- rauhl 5y ago> The difference between this and a full lisp like Clojure is that this must be turing-incomplete. Sure, but one could still implement a Turin-incomplete language in S-expressions. It would be more readable and more succinct, too.
- joshlemer 5y agoBut who cares? The fact that the syntax of this language is JSON-based rather than S-Expression based is an odd point to have the majority of commenters nitpicking about. When somebody posts an interesting new service to Hacker News, we don't have similar comments saying "why does this api serve up JSON and not S Expressions / Protobuf / Avro / CSV / XML???" What about regular every day programming languages? When a language is posted to Hacker News we don't laugh them out of the room with "hahah! Why didn't you use S expression syntax for this language??"
- kemitchell 5y agoThis has been independently reinvented countless times, in countless languages. Would be nice to get a somewhat generalized standard in place.
- TeMPOraL 5y agoIt's called, "use a Lisp, dammit!". Seriously. There are Lisp languages that could replace whatever language you're using, and, there are also Lisp languages/runtimes that you could embed in whatever language you're using, to avoid rewriting it from scratch like this.
- skybrian 5y agoWhich lisp though? There are still too many choices. The fact that people say "use a lisp" instead of "use Lisp X like everyone else" should tell you something. It's like the difference between "use SQL" and "use SQLite" or "use Postgres."
- TeMPOraL 5y ago> Which lisp though? Whichever works best for your particular constraints. > It's like the difference between "use SQL" and "use SQLite" or "use Postgres." Precisely! "Use Postgres" is a valid answer to the question, "which database should I use?", or "which relational database should I use?". And "use SQL" is a valid recommendation when you see someone reinventing relational data model and reimplementing a relational database without realizing it. Similarly, "use a Lisp" is a valid recommendation when you see someone reinventing programming using trees from first principles - of which a telltale sign is reinventing s-expressions.
- skybrian 5y agoWhich Lisp would you recommend for a config file that has a few business rules in it, when the rest of the system isn’t written in Lisp?
- mplanchard 5y agoWe built a rust version of this that provides a Python package via CFFI and a node package via WASM, because we found that the different implementations for different languages were pretty buggy and would sometimes resolve expressions differently. Also the original project in JS seems to be largely unmaintained. The rust version goes to great lengths to reimplement weird JS typecasting so as to be fully compatible with the original. https://github.com/Bestowinc/json-logic-rs https://github.com/Bestowinc/json-logic-rs I am currently working on an extension to add functions and more strongly typed operators to avoid the hassle of JS’ type conversion. That extension will probably be released as a separate package, because I am no longer with Bestow.
- rendall 5y agoFor some reason, this project seems to be drawing rather nasty comments. I'd like to remind everyone of the guidelines: Be kind. Don't be snarky... Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something.
- commandlinefan 5y ago"This is a bad idea" is neither nasty nor snarky.
- rendall 5y agosebmellen, I looked at its repo and it's just the license? Am I missing something?
- sebmellen 5y agoJust to be clear — not my project, but I’m trying to use this or something like it. I found it pretty compelling though also somewhat lacking, and HN is a great place to get more discussion and maybe read about some alternatives :)
- geuis 5y agoCould someone explain why this or similar projects are useful?
- coldtea 5y agoFor defining (and allowing users to touch) more powerful than static configuration and/or business logic, that you don't want to be turing complete.
- fomojola 5y agoIt is a DSL for additional logic that can be: - Stored in your existing data store (assuming your data store can store a string) - Executed without eval() or any other potentially dangerous method - Executed in bounded time You think of things like Lua in Redis: this is one take on a not-quite-as-capable alternative for logic that can be safely executed in restricted environments (barring errors in the implementation of the parser). There will be editing/verification requirements: writing any moderately complex logic structure without a designer/test evaluator would be a nightmare, but as a generic way to specify/embed custom logic in a system that is language independent, has effectively no additional parser requirements (given that just about every single language has a JSON parser that is probably already in use in your project) it isn't a completely bad look. S-expression parsers do exist, but I'd wager many more people are familiar with the JSON parser in their language than the S-expression parser available in their language. I will say: it isn't complete. It lacks clarity about the behavior in the face of missing/invalid operation arguments. Something like {"<" : ["ham", 42]} I'd assume would throw an evaluation exception of some kind, but that should be clear in the spec. The playground at https://jsonlogic.com/play.html https://jsonlogic.com/play.html is a start, but before you try handing this to a non-developer, you'd really want a visual editor with node folding of some kind (so you can hide deeply nested structures away while you work on other things), variable completion (so you specify a sample data object and if you're typing in a variable you get completion options) and operator parameter verification (to stop you from writing in incorrect/unsupported values based on the operator).
- ar-nelson 5y agoI've been trying to invent a JSON-Lisp language like this for a long time. My first attempt was Jaspr (https://github.com/ar-nelson/jaspr https://github.com/ar-nelson/jaspr), which has its own syntax that compiles to JSON. But I'm working on a new, Turing-incomplete variant called MiniJaspr that fills a similar niche to config languages like Jsonnet or Dhall.
- beaconstudios 5y agoif you're wanting to reuse the same logic on both backend and frontend, you can just use JS on the frontend and backend and pull your functions/utilities in from a shared library - either a git submodule, private NPM package or (my preference) have all three running inside a yarn workspaces monorepo.
- dvt 5y agoThis is a fun project and a cute reinvention of Lisp, as people have already mentioned. I think people are snarky because if this was just a fun project, that would be the end of it. But it seems like JsonLogic is trying to be an actual thing. And this latter point is why it's just a monumentally terrible idea. I mean.. just look at the Custom Operations wiki[1]. It's honestly just horrible -- horrible -- and may actually even summon Zalgo[2]. This is exactly how we ended up with the XML nightmare of the late 90s/early 2000s. JSON is not meant to be programmable. Please, for the love of all that is holy, stop. [1] https://github.com/jwadhams/json-logic-js/wiki/Custom-Operations https://github.com/jwadhams/json-logic-js/wiki/Custom-Operat... [2] https://stackoverflow.com/a/1732454/243613 https://stackoverflow.com/a/1732454/243613
- vesinisa 5y ago> Please, for the love of all that is holy, stop. Yes! Oh my god, this. I remember how XML ended up being abused to express Turing complete logic in too many instances. Then they even specified an XML format to transform other XML documents, called XSLT, which is itself Turing complete. It really makes my head hurt. I think why people gravitated away from XML was because it had become a convoluted mess. The JSON specification is terse on purpose, famously enough so to fit on a business card. If you want to abuse JSON to express logic, please keep it as your dirty little secret.
- nitwit005 5y agoThe moderator's note on #2 adds a lot to the amusement.
- ctoth 5y agoThis project reminds me quite a bit of [0] which I'm currently using to write rules to parse tags from Openstreetmap. Having a standard way to share expressions does seem quite useful, especially when it's multilingual. [0]: https://github.com/google/cel-spec https://github.com/google/cel-spec
- sebmellen 5y agoVery nice, had not heard of this before. I will take a close and careful look.
- dan-robertson 5y agoThis sort of rule language you can put in configs is often useful. They tend to eventually cause problems as logic that should have been implemented properly gets embedded in the mini language and the little rules get more and more complicated (or even auto-generated from a simpler specification), but they are invaluable while they do work. One thing that surprised me was the inclusion of map/reduce/cat. Allowing these operators can make runtime exponential in the size of the program. I feel like that is against the spirit of the language.
- mcphage 5y agoI don't understand why they represent it as a object with a single key, whose value is an array: - If it's an object, then nothing is going to enforce there only being one key. - If it's a unary operator, then the value doesn't need to be wrapped in an array, but then how does it distinguish between an unary operator, whose operand is an array, vs. an n-ary operator? Both of these problems would be solved by having each clause be an array, with the first value being the operator, and the rest of the operands being the parameters. That way having multiple operators isn't even syntactically possible, and having multiple operands is just as simple as the unary operand case.
- flying_sheep 5y agoIMHO coding logic in JSON is similar to puzzle game. I would recommend to use jq instead.
- spankalee 5y agoI think avoiding a parser by using JSON is kind of neat, but it really isn't that difficult to write a parser for a small expression language and you get the benefit that you can expose a much nicer syntax to end users with the same parser - rather than having an standard AST and need a parser anyway to have decent UX. I work on and off on a very simple syntax language for things like templates, but would be well suited towards business rules and such too. It was the first parser I wrote outside of school and pretty easy to understand, small and fast too: https://www.npmjs.com/package/jexpr https://www.npmjs.com/package/jexpr
- ivan888 5y agoProbably the biggest benefit of using something like JSON is the fact that you can safely and easily generate dynamic code without having to worry about different quirks of the particular grammar
- weatherlight 5y agoman, I implemented a rules engine library where i expressed, the rules as S-Expressions (basically a lisp) that mapped to ruby lambdas. that way when finance would come back and be like, "what was the logic and the rules at a given point of time, I could point to what the rule was, what was it configuration, and who changed the configuration or the rule." and the rule execution strategy. It works, I'm proud of it, the lisp layer is completely abstracted away from the developers and the users who configur ed the rule. I thought I was so clever :) Apparently, engineers have a habit of doing this.
- ardit33 5y agoAnd the circle of life continues! I have seen exactly this method in 2004-2006 but with XML. If you are reading this, and you think it is a good idea, please don't follow it as it is not. Back in 2006-2009 I worked at MobiTV, which we had the same exact way/method of programing our mobile apps, on J2ME/feature phones. The made up language was called CEF which was based on XML. While the idea is sound in paper, This turns really fast into an ugly, debug everywhere type of scenario, where it is hard to both develop and debug properly. The only way this is ok, is when you have some fully automated UI tool, that stores some kind of state, and retrieves it back, but with no human intervention and some very very limited logic. Otherwise you are in a world of pain. If you try to include real application logic into something like this it is going to hurt your business long term. It will turn your business logic like some Maven configuration, full of gotchas and more.
- jchw 5y agoI am not saying that you are wrong. Not at all. However, something I’ve come to learn is that some ideas I thought were bad were actually not bad. They were poorly executed and the exact reasoning why they did not work well in a given application was not well-understood. So I can see an argument for “this was horrible back when it was done in the early 2000s” simultaneously with “this could actually still be a good idea for some use cases.”
- janderland 5y agoCurrently reading about agriculture throughout human history. It made me wonder how many people failed to domesticate a single kind of crop and assumed crop domestication as a whole isn’t a good idea. I realize that people need to make decisions based on their personal experience, and I don’t have a good rule-of-thumb for when to try a variation of a “bad” idea.
- marksbrown 5y ago‘Many of life’s failures are people who did not realise how close they were to success when they gave up' -- Thomas Edison.
- arthurcolle 5y agoNot sure why this is getting so much hate, I think it's pretty cute. Can't really imagine when I'd use it, but i like it.
- papito 5y agoImagine trying to configure rules in a CMS without touching code. I work at a place that does it. They may... be using this.
- laurent123456 5y agoHmm... unversioned, untestable code saved in a database. What could go wrong.
- papito 5y agoNo this is not code - this is configuration. Many places actually save CODE into the DB and then load it at runtime for, say, ETL jobs. It's not an easy problem.
- arthurcolle 5y agoNot if they are using Airflow :)
- mtone 5y agoI’d argue that in some cases it can be more testable than code. With a small, strict subset of a turing-complete language and constrained input choices, you can often auto generate test cases for any valid expression in a given context. Static analysis of code is much more difficult and broad. One thing code versioning doesn’t do well either is executing multiple versions of the same logic. With rules as data, you can store them as timestamped versions and keep applying the correct historical rule against some older business object or view.
- jsd1982 5y agoThe logo is pretty clever
- diegoholiveira 5y agoI did a rules engine to the company that I work based in this specification, but using go language. It is a very successful project because our clients can create rules without tech people around in our frontend, it's very easy to translate our rules into json and store it. I even did a library to implement it in go language: https://github.com/diegoholiveira/jsonlogic https://github.com/diegoholiveira/jsonlogic
- lloydatkinson 5y agoIs this a recent project? Anything using that ancient theme looks... ancient.
- closeparen 5y agoWe are quite successfully using Starlark for an embeddable, executable config language. For example, I can take a Starlark expression at the command line and use it to filter elements of a collection. https://github.com/bazelbuild/starlark https://github.com/bazelbuild/starlark
- karambir 5y agoWe used this at an early version of ad-network where Advertisers would write JsonLogic against a set of user properties with all the operators. And this was checked at runtime when ad was to be shown. At the time, I thought this was a neat and quick way to give advertisers some form of targeting. We had ~500 active ad campaigns at any given time(not much growth beyond that) and this worked really great. But I always thought there should be better way for this kind of application. I see a lot of comments about Lisp. My question is: Is Lisp better for above scenario or there is even better way?
- natn 5y agoI built something like this once for defining form validation rules. It was fun. I was very proud of it. I'd probably just use JSONSchema now though.
- sheminusminus 5y agoAt Routable we use this to power a significant portion of our dynamic UI (super complex forms with interwoven dependencies, etc). Super cool and useful library with a surprisingly low number of gotchas for what it's doing. We did a little write-up about our experience with it here if anybody is interested: https://blog.routable.com/tablematic-a-tale-of-server-driven-ui/ https://blog.routable.com/tablematic-a-tale-of-server-driven...
- sebmellen 5y agoThank you, this kind of real-world experience and feedback is exactly what I was looking for when making this post! I will take a read through that blog :).
- remram 5y agoWhat is the advantage of this being JSON? Couldn't the language be more "terse, consistent, secure, and flexible" if it wasn't JSON, with the possible advantage of parsing faster and being friendlier to write? The website lists the ability to easily send it "between front-end and back-end code, and even store it in a database", is there an advantage to it being JSON for any of these goals?
- pjerem 5y agoWe blindly use JSON for everything because one day, someone discovered that JavaScript embedded a JSON parser called eval(). Yup, that’s where our civilization is.
- skybrian 5y agoProgrammers are already familiar with the surface syntax, including gotchas like only having doubles. Also, the logic can be embedded in an already-existing JSON file. This is useful if you occasionally need to look at the file, but usually you don't, so it's not worth putting any more effort into nice tooling.
- dec0dedab0de 5y agoI can see using this for writing validators that can be written once, then ran on the api and frontend. I'm struggling to think of another use.
- ekimekim 5y agoThe niche that immediately came to mind when I saw this was allowing a user to specify a filter expression for some query, either as a simple text-based language or using some sort of UI (with drop-downs and such). Having a well-established spec with existing libraries for turning these kinds of expressions into an AST for transfer, storage, execution later, etc is valuable. I've definitely implemented a simplified, domain-specific version of this kind of thing in various projects over the years.
- brundolf 5y agoMapbox's API has something similar, except they use the first element in an array for the operator instead of an object key: https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/ https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/ Some will recognize that these are basically just Lisp s-expressions (as JsonLogic also seems to pretty much be) "Code as data" indeed
- daenz 5y agoLike wasm, the idea of portable logic is interesting. Unlike wasm, this is the wrong vehicle for it. And this implementation's very-limited nature means that anyone who buys into it will need to rip it out when the limited logic inevitably doesn't scale with the rest of their applications.
- forgetfulness 5y agoSince you can't expand rules into any other rules, yes, it's pretty restricted. Kind of a feature though.
- rubyist5eva 5y agoI worked at a marketing company and we had a targeting engine that was basically this, but not as elegant. Will give this a try this weekend and see how it compares in practice, cool project.
- codeulike 5y agohttps://en.wikipedia.org/wiki/Inner-platform_effect https://en.wikipedia.org/wiki/Inner-platform_effect That said, I think everything has uses in some circumstances; there are no rules in software that are beyond debate
- erulabs 5y agoProbably not appropriate for a large poly-glot organization, but I really like creating shared JS libraries that can be used in the browser and also in Node.js apps. For game development, having the game logic in a shared library makes server-side validation and client-side prediction really easy and prevents code duplication. I'm sure there is some reason it's all a horrible idea but almost all my projects these days use React front-ends and Node.js back-ends and a shared library used by both, ideally containing most of the complex logic. This seems like a neat version of that that might be useful in an organization which uses many different languages.
- orasis 5y agoThis is almost always a bad idea. It’s best to find a way to use a full blown programming language for these types of customization.
- shadeslayer_ 5y agoNot to be that guy but didn't we agree about moving business all business logic into a single place, back in 2012?
- atatatat 5y agoWhat if I use this as a read-only API of sorts for sending regular reports from a Blazor app db to legacy systems?
- asah 5y agoplease no. just no.
- asah 5y agoplease no. just no. "Logic" is lazy word for "code" and we saw what happened when Excel "macros" grew up into major applications. To be safe under maintenance, safe vs security, etc code needs at least these things: - source control - docs (and ideally, examples) - tests (and ideally, CI)
- alex7o 5y agoCan I ask why do we need to embed lisp in JSON, can't we just serialise our lisp to JSON?
- bww 5y agoThe idea of representing an expression as an abstract syntax tree for interchange is not an inherently bad idea. Trying to shoehorn a general purpose data interchange format into a highly specialized application like that is a common anti-pattern, however. When I see this sort of thing (which I assume was inspired by MongoDB's own atrocious "query language") I'm always surprised by the fact that many engineers don't seem to be aware of how easy it is to write a parser that is actually designed for the data you're trying to represent. At least "easy" in the context of undertaking a project that is attempting to generalize this exact problem. JSON is a fine interchange format until you need a specialized runtime to evaluate the data, which is what is happening here. At that point there's zero benefit to using a general purpose interchange format just because it already exists: just write a DSL. A good place to start: https://www.antlr.org/ https://www.antlr.org/
- imoverclocked 5y agoI get it. I do ... it still rubs me the wrong way because: 1) You are leveraging a JSON parser to get strings 2) The strings contain tokens that need to be "parsed" 3) You turn this double-parse into an AST I see this pattern all too often. If you create (or re-use an existing) grammar that is specific to the problem domain then you get a much faster parse, smaller data transfer/storage, and a more human-readable format.
- mmaug 5y agoCongrats! You've invented a verbose version of LISP...
- gloryless 5y agoThere are a ton of scenarios where this would be useful. Not everything has to be the new paradigm shift. It's just a tool
- lootsauce 5y agoThere are legitimate uses for such things. We are currently implementing a processing rules configurator UI and backend that must ultimately be executed in sql. It must support arbitrary nested boolean logic and comparison expressions. Last time we did this we ended up developing a custom data structure for the front-end and a custom printer for the sql output. This is a standardized version of solving just that problem. My question is if not a solution like this how then SHOULD I be implementing communication of such rules from the frontend to the backend?
- garren 5y agoIt reminds me of this [0] post from a few months back which implements something more or less similar using js arrays as a kind of sexp. I’m working with a system that relies extensively on logic implemented as json structures. We’re not using this lib, I found it to be difficult to follow and more difficult to debug. Ymmv, but I’d definitely think hard before leaning on something like this. [0] https://stopa.io/post/265 https://stopa.io/post/265
- devit 5y agoThat seems worse than using the common C/Java/JavaScript syntax for operators and function calls, that can be easily parsed with any JavaScript parser.
- Lapsa 5y agoeval("temp < 110 && pie.filling == 'apple'")
- nsonha 5y agoit's only a matter of time before you are called gatekeeper because "json is a programming language" I remember when I was an university student thinking writing java in XML (Spring) was cool. Man I was dumb.
- AcerbicZero 5y agoI am firmly on team “anything but YAML” so perhaps I’ll give this a try next chance I get.
- nikolay 5y agoSo, pretty much everything we've done in XML is now available in JSON. Wasn't the purpose of JSON supposed to be getting rid of XML's complexity?! Same with JavaScript - it was supposed to be a dynamic typing language, now most of the serious code migrated to the type safer TypeScript. We just keep going in circles and wasting so much energy! This is not progress; it literally is chasing our own tail!
- chrismorgan 5y agoThe one thing that’s bugging me about this is the particular JSON structures employed. They’ve gone for this: {"*operator*": [...args]} With one special case: {"*operator*": single_arg} (This special case confirms that JsonLogic isn’t using arrays as a top-level construct, otherwise it’d be ambiguous. Well, it confirms either that or that it’s even worse-designed than it looks. Anyway, I’m going to assume arrays are free to use as a top-level construct.) In short, you end up using an object and an array for each element. Yet the object is strictly being used as a two-tuple, and objects are a roundly bad idea for this application: the only way you’re ever going to be looking at it is “it’s an object, confirm that it has only one pair in it, then pull the first key out, and pull its value out”. This is quite inefficient in both memory and runtime performance. The only thing it really has going for it is that it guarantees that the key is a string, which is significantly overrated given the other more expensive bits of validation and access costs that it forces. So the whole thing would be made more efficient (and arguably even more robust) by just changing it to an two-element array: ["*operator*", [...args]] ["*operator*", single_arg] And then the natural next step is to say “why are we using two arrays rather than just one?” and flatten it into this: ["*operator*", ...args] This is conveniently shorter to type, and eliminates the nasty single-argument special case too. That’s very probably going to be more efficient on fixed-arity operators (which is most of them) and on potentially-unary operators, though it’s possible that it may be more expensive on larger calls if you need to slice the array during evaluation in order to exclude the operator. So the end result I’ve suggested here is simpler, more consistent, smaller on the wire and in memory, faster, more robust across diverse languages and environments—in short, superior in pretty much every way. The only real place it might not be superior is auto-formatting, where you lose probable separation of arguments from operator (subjectively often desirable) but reduce the indentation level by one (more strongly desirable). It’s also more S-expressiony!
- Seb-C 5y agoI've been there, done (Something like) that and I'd rather duplicate code than doing this ever again.
- wyqydsyq 5y ago> If you’re looking for a way to share logic between front-end and back-end code So... exactly like isomorphic/universal JavaScript? What exactly is the practical benefit in this, compared to say, JS functions shared by serialising them as strings or by abstracting them into a common dependency package which can be ran both on front-end and back-end?
- justsomeuser 5y agoI think I would rather just let the logic-writer user use JS directly, and then verify the AST only uses certain language features. This way you can ensure the code is a subset of JS (the same subset of JSON-Logic), whilst using all the tools and runtimes of JS.
- ashneo76 5y agoUhh.. json doesn't have comments. There is no code readability in here. If you are trying to represent code in data, night as well go use a language for that. This is still a cool project. It issues a lot of effort to build something like this. But I wouldn't use it for production until this has been around for a while and json gets comments.
- hmmx3 5y agoLooks like a lisp
- hmmx3 5y agoLooks like lisp