[HN Gopher] JsonLogic
       ___________________________________________________________________
        
       JsonLogic
        
       Author : sebmellen
       Score  : 186 points
       Date   : 2021-05-27 18:16 UTC (4 hours ago)
        
 (HTM) web link (jsonlogic.com)
 (TXT) w3m dump (jsonlogic.com)
        
       | millerm wrote:
       | Seems 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?
        
         | joshlemer wrote:
         | ClojureScript does not complete in a deterministic amount of
         | time, on account of it being a turing-complete programming
         | language.
        
         | eevilspock wrote:
         | Thank you. I'm going to take a look at this for the project I
         | mentioned in my other comment.
        
         | [deleted]
        
         | sebmellen wrote:
         | I'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)...
        
           | renewiltord wrote:
           | I might be misunderstanding, of course, but would you be able
           | to use the JSON protobuf serializers and just define your
           | conditions as Protocol Buffers?
           | 
           | Might be heavyweight.
        
             | jimsimmons wrote:
             | This is not a bad idea. But coupling with protocol buffers
             | is an issue and JSON doesn't have a standardised way to
             | parse expressions
        
             | sebmellen wrote:
             | I think it's best to direct your attention here as the
             | comment is rather lengthy and takes up a lot of vertical
             | space: https://news.ycombinator.com/item?id=27307631.
        
           | mixedCase wrote:
           | S-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 wrote:
             | The problem with s-expressions is that you can't include
             | them within an already extant JSON schema.
        
       | eevilspock wrote:
       | Essentially 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.
        
       | rendall wrote:
       | For 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 wrote:
         | "This is a bad idea" is neither nasty nor snarky.
        
       | ktpsns wrote:
       | And 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)
        
         | pydry wrote:
         | It's Turing incomplete. Like HTML.
         | 
         | LISP is, on the other hand, a programming language. It's rather
         | famous for it.
        
         | [deleted]
        
         | adamkl wrote:
         | Here's some great instructions on how to use JSON to do just
         | that:
         | 
         | https://stopa.io/post/265
        
         | joshlemer wrote:
         | Are 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.
        
       | jsd1982 wrote:
       | The logo is pretty clever
        
       | sheminusminus wrote:
       | At 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...
        
         | sebmellen wrote:
         | Thank 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 :).
        
       | AcerbicZero wrote:
       | I am firmly on team "anything but YAML" so perhaps I'll give this
       | a try next chance I get.
        
       | dvt wrote:
       | This 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-
       | Operat...
       | 
       | [2] https://stackoverflow.com/a/1732454/243613
        
         | vesinisa wrote:
         | > 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.
        
       | Lapsa wrote:
       | eval("temp < 110 && pie.filling == 'apple'")
        
       | code-is-code wrote:
       | I 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
        
         | sebmellen wrote:
         | Thanks 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.
        
       | ctoth wrote:
       | This 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
        
         | sebmellen wrote:
         | Very nice, had not heard of this before. I will take a close
         | and careful look.
        
       | remram wrote:
       | What 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 wrote:
         | We 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 wrote:
         | Programmers 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.
        
       | IshKebab wrote:
       | Ha they heard of "truthy" and "false" but apparently stopped
       | reading before "... are a really really terrible idea!".
        
         | mcphage wrote:
         | What'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 wrote:
           | There 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 wrote:
             | Sure, 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.
        
       | nsonha wrote:
       | it'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.
        
       | telekid wrote:
       | That'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
       | 
       | [2] https://blog.sigplan.org/2019/12/30/defunctionalization-
       | ever...
       | 
       | [3]
       | https://www.cis.upenn.edu/~plclub/blog/2020-05-15-Defunction...
        
         | joshlemer wrote:
         | The 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. "
        
       | lootsauce wrote:
       | There 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?
        
       | dec0dedab0de wrote:
       | I 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 wrote:
         | The 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.
        
       | rendall wrote:
       | sebmellen, I looked at its repo and it's just the license? Am I
       | missing something?
        
         | sebmellen wrote:
         | Just 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 :)
        
       | diegoholiveira wrote:
       | I 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
        
       | bww wrote:
       | The 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/
        
       | kemitchell wrote:
       | This has been independently reinvented countless times, in
       | countless languages. Would be nice to get a somewhat generalized
       | standard in place.
        
         | bob1029 wrote:
         | We do something almost like this, but we didn't try to invent
         | any of the hard bits. We serialize our domain instances into
         | JSON documents which also happen to contain the business rules
         | as in-line SQL properties, and then project this JSON document
         | into SQL databases as required for evaluating business logic.
         | 
         | Ephemeral, in-memory instances of SQLite can be incredibly
         | powerful tools for building an extensible business logic
         | engine.
        
           | idolaspecus wrote:
           | Could you expand on this idea a bit more? My curiosity has
           | been piqued, but I'm not sure I really understand the system
           | you've described.
        
             | bob1029 wrote:
             | The combining of JSON & SQL is mostly inconsequential here.
             | It is just a convenience for sending things in 1 file vs
             | multiple.
             | 
             | The big takeaway is that SQL is a really great tool for
             | exposing any sort of customizable logic over arbitrary
             | datsets.
             | 
             | The only major caveat with this - You will typically have
             | to perform some degree of transformation over source data
             | in order to achieve a form of normalization well-suited to
             | the writing of business logic (SQL). Assumptions (i.e.
             | denormalizations beyond 3NF [0]) made in your schema here
             | will inevitably hamper or kill the ability of the business
             | to write flexible queries which can satisfy real-world
             | needs. Today, a customer may have multiple accounts. In a
             | few years, maybe we decide it goes the other way too. If
             | you made an assumption, such as nesting these complex types
             | in any way whatsoever, you are probably stuck with a
             | steaming bag of shit that you now have to refactor and
             | retest top-to-bottom. Using relation types to decouple
             | nested complex types is the core tenant in my mind.
             | Identity is foundation, but you can fudge your way around
             | that a little bit.
             | 
             | This one caveat is why a lot of developers look at this
             | idea as a bad one at face-value. It takes a lot of work &
             | iterations with the business stakeholders to get this
             | correct. You can't sit in a silo and expect to completely
             | figure out the abstract nature of business types or learn
             | how they might be related and in what ways. There really is
             | a "correct" and "incorrect" way to go about it if you are
             | being properly academic. Worry about webscale and
             | performance later. Get it correct first. Nothing is too
             | complex for a SQL schema.
             | 
             | If you can satisfy the academic gods of normalization and
             | achieve a stable schema, then you are in for a wonderful
             | ride. Between using views to compose higher-order
             | functions, and UDFs [1] to wire into customized SQL
             | functions, you can satisfy literally any degree of
             | complexity required by the business. The only limit is your
             | ability and discipline around modeling the domain types &
             | relations, and willingness to get your hands dirty with
             | some views and functions. You will find your business
             | experts loving the power they gain by being able to write
             | queries in a domain specific language they inherently
             | understand. Giving them higher-order functions (views) and
             | iterating on that side of the fence is yet another gigantic
             | value play that is invisible if you are looking anywhere
             | other than SQL.                 [0]:
             | https://en.wikipedia.org/wiki/Third_normal_form       [1]:
             | https://www.sqlite.org/appfunc.html
        
               | idolaspecus wrote:
               | Thanks for the detailed response!
        
         | TeMPOraL wrote:
         | It'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 wrote:
           | Which 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 wrote:
             | > _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.
        
       | joshlemer wrote:
       | A 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.
        
         | tgbugs wrote:
         | They 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-
         | in...
        
           | ironmagma wrote:
           | > 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.
        
           | shawnz wrote:
           | With 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.
        
         | whalesalad wrote:
         | Ultimately 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.
        
           | forgotmypw17 wrote:
           | I think it's just a natural law that information tends to
           | "crystallize" into certain patterns, and we're just the
           | implementors of those repeating patterns. :)
        
           | joshuamorton wrote:
           | https://github.com/joshuamorton/tidbits/blob/master/lispy.py.
           | ..
        
           | sebmellen wrote:
           | The most important difference to me is that this is usable
           | within already extant JSON Schemas that can be patched up or
           | added to.
        
           | athrowaway3z wrote:
           | I remember years ago when i first came to hackernews there
           | was a project very similar to this. An engineer blog proud of
           | the AST they encoded as JSON.
           | 
           | I had only a vague idea of what an AST was, but the highest
           | upvoted comment was clearly saying: This is dumb, we have
           | dedicated formats for turning text into ASTs. ( i.e. a
           | programming language ).
           | 
           | In the past decade+? i have learned what an AST is and have
           | now twice, in a professional setting, prevented an engineer
           | from re-inventing this very concept.
           | 
           | If i had to choose if hackernews is a place where smug snark
           | comments crack down on re-inventing known concepts or a happy
           | place where every idea is a good one i will choose the
           | former.
           | 
           | And once every blue moon we get to laugh and look back at
           | snarky comments such as this:
           | https://news.ycombinator.com/item?id=9224
        
             | samatman wrote:
             | I don't understand this at all.
             | 
             | JSON is a serialization format. So say you have an in-
             | memory AST, and you want to serialize it: why not use JSON?
             | 
             | If you don't want or need to serialize it, then of course
             | don't use JSON. I can make up plenty of other reasons not
             | to, but they're variations on some other format being
             | better for the application, not JSON being inadequate in
             | any way. I'd probably use JSON myself, and I don't care for
             | it much.
             | 
             | Or are we talking about building up an AST in JSON
             | _directly_ rather than taking some parser output and
             | serializing it? Ok that 's... not an AST then, it's a
             | programming language with JSON compatible syntax, and yes I
             | would try and prevent that from getting implemented as
             | well.
        
             | incrudible wrote:
             | Yes, we have programming languages. Lots of them. Most are
             | distinguished by what you can do with them. Few are
             | distinguished by what you can _not_ do with them.
             | 
             | This is one of the few projects addressing the latter
             | problem space.
        
           | brundolf wrote:
           | The difference is the collection of extremely powerful
           | parsers, tooling, language support, etc that already exist
           | for this syntax. There's a proper Content-Type header,
           | blazing-fast native parsing in web apps, you could store it
           | directly in MongoDB or the like without an extra
           | serialization/parse step, you could query it with jq. Heck,
           | you could statically-check these expressions using
           | TypeScript.
           | 
           | Lispers are always pointing out how the parenthesis-and-
           | whitespace notation is just incidental; how s-expressions are
           | really something deeper that isn't bound to a specific
           | syntax, and how this is a strength. The OP is a
           | _demonstration_ of that strength.
        
           | pydry wrote:
           | >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 wrote:
             | >>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 wrote:
               | Well, the most famous example most definitely is.
               | 
               | There's thousands of ways this could have been encoded.
               | Why that one specifically?
        
             | remram wrote:
             | Correct 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]
        
           | [deleted]
        
         | yongjik wrote:
         | I 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 wrote:
           | Don'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.
        
         | eevilspock wrote:
         | Here'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.
        
       | brundolf wrote:
       | Mapbox'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/
       | 
       | Some will recognize that these are basically just Lisp
       | s-expressions (as JsonLogic also seems to pretty much be)
       | 
       | "Code as data" indeed
        
       | lloydatkinson wrote:
       | Is this a recent project? Anything using that ancient theme
       | looks... ancient.
        
       | codeulike wrote:
       | 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
        
       | imoverclocked wrote:
       | I 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.
        
       | dan-robertson wrote:
       | This 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 wrote:
       | I 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 wrote:
       | IMHO coding logic in JSON is similar to puzzle game. I would
       | recommend to use jq instead.
        
       | daenz wrote:
       | Like 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 wrote:
         | Since you can't expand rules into any other rules, yes, it's
         | pretty restricted. Kind of a feature though.
        
       | gloryless wrote:
       | There are a ton of scenarios where this would be useful. Not
       | everything has to be the new paradigm shift. It's just a tool
        
       | erulabs wrote:
       | Probably 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.
        
       | closeparen wrote:
       | We 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
        
       | orasis wrote:
       | This 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.
        
       | geuis wrote:
       | Could someone explain why this or similar projects are useful?
        
         | fomojola wrote:
         | It 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 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).
        
         | coldtea wrote:
         | For defining (and allowing users to touch) more powerful than
         | static configuration and/or business logic, that you don't want
         | to be turing complete.
        
       | karambir wrote:
       | We 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?
        
       | spankalee wrote:
       | I 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
        
       | mmaug wrote:
       | Congrats! You've invented a verbose version of LISP...
        
       | garren wrote:
       | It 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
        
       | shadeslayer_ wrote:
       | Not to be _that_ guy but didn 't we agree about moving business
       | all business logic into a single place, back in 2012?
        
         | atatatat wrote:
         | What if I use this as a read-only API of sorts for sending
         | regular reports from a Blazor app db to legacy systems?
        
       | mplanchard wrote:
       | We 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
       | 
       | 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.
        
         | goodpoint wrote:
         | > rust version of this that provides a Python package via CFFI
         | and a node package via WASM
         | 
         | I honestly thought it was parody around the unnecessary
         | complexity of modern software.
        
         | sebmellen wrote:
         | Wow, awesome. Thank you! Just the kind of thing I'm looking for
         | :)
        
       | ar-nelson wrote:
       | I'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), 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 wrote:
       | if 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.
        
       | weatherlight wrote:
       | man, 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.
        
       | natn wrote:
       | I 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.
        
       | asah wrote:
       | please no. just no.
        
       | devit wrote:
       | That seems worse than using the common C/Java/JavaScript syntax
       | for operators and function calls, that can be easily parsed with
       | any JavaScript parser.
        
       | ardit33 wrote:
       | And 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.
        
         | sebmellen wrote:
         | Maybe you can tell me if there's a better solution. I'm open to
         | hearing any options because I'm at a loss of how to do this
         | otherwise:
         | 
         | Say we have a schema which defines certain data. Let's say it's
         | a "credential" which is a "COVID-19 Back to Work Credential."
         | The credential is valid in the case that someone either 1) has
         | a COVID vaccination _or_ 2) has a negative COVID test in the
         | past 72 hours. That data might look like this:
         | {         "credentialName": "COVID-19 Back to Work Credential",
         | "credentialIssuer": "Acme Labs Inc.",         "credentialData":
         | {           "rapidSarsCov2PCRTest": {
         | "hasTestResult": true,             "testResult": "negative",
         | "testTime": 1622145851           },
         | "covid19Vaccination": {             "hasVaccination": false
         | }         }       }
         | 
         | Now, say I want to define the conditions under which this
         | "credential" is valid or invalid, but I want to include this
         | "matrix" within the schema (not any business logic, just matrix
         | logic that pertains to the data _within the schema itself_ ).
         | 
         | Optimally, I'd be able to do this within the same schema or
         | file.
         | 
         | With JsonLogic, that might look like this (probably flawed
         | logic, just a demo, not using this in production, may cause
         | your computer to go up in flames, etc.):                 {
         | ...              "parsingMatrix": {           "if": [
         | {               "or": [                 {
         | "===": [                     { "var":
         | "credentialData.rapidSarsCov2PCRTest.testResult" },
         | "negative"                   ]                 },
         | {                   "===": [                     { "var":
         | "credentialData.covid19Vaccination.hasVaccination" },
         | true                   ]                 }               ]
         | },             "valid",             "invalid"           ]
         | }       }
         | 
         | Can you think of another way to do this that doesn't rely on
         | using JsonLogic or something like it (or a cleaner method for
         | doing it in JSON)?
        
           | goto11 wrote:
           | How about representing the logic as a JavaScript expression:
           | (credentialData.rapidSarsCov2PCRTest.testResult==='negative')
           | || credentialData.covid19Vaccination.hasVaccination)
           | ? 'valid' : 'invalid'
           | 
           | Seem easier to read and maintain to me.
        
             | sebmellen wrote:
             | I'd love to do this, the only problem there is we're
             | sharing this data between systems which use different
             | runtimes. A client who runs a Python environment might not
             | easily be able to make use of that logic. With JsonLogic,
             | that would theoretically be possible.
        
               | goto11 wrote:
               | You can easily write a parser for this in Python. As long
               | as you only support expressions it should be pretty
               | straightforward.
        
               | sebmellen wrote:
               | I see your angle. I'll consider this. Thanks for the
               | ideas!
        
               | adamkl wrote:
               | I posted this in another thread, but it seems relevant to
               | what you are looking for: https://stopa.io/post/265
               | 
               | It walks through the process of building a Lisp in JSON
               | and the associated parser in JavaScript. It could be a
               | good starting point to build out a cross-platform
               | approach to sending logic over the wire.
        
               | sebmellen wrote:
               | Nice, looks quite neat. I'll dive into it a bit deeper!
        
               | chousuke wrote:
               | I can't help but think that at the end of this road is
               | yet another Lisp waiting to be discovered.
        
           | contravariant wrote:
           | What about:                   ["if", ["or", ["===", ["var",
           | "credentialData.rapidSarsCov2PCRTest.testResult"  ],
           | "negative"],                       ["===", ["var",
           | "credentialData.covid19Vaccination.hasVaccination"],  true
           | ] ],                "valid",                "invalid"]
           | ?
        
             | sebmellen wrote:
             | That's nice, I like it! We don't really need anything more
             | than this.
             | 
             | It's hard to gauge whether or not it's better to go with an
             | existing, possibly inferior standard, or to create a new
             | one, like this...
             | 
             | https://xkcd.com/927/
        
               | contravariant wrote:
               | I mean it is just lisp denoted in javascript lists, but
               | sure we can call it a new standard if you like.
        
               | sebmellen wrote:
               | If this works out we'll either be adopting a previous
               | standard or defining a new one for these evaluation
               | matrices!
               | 
               | But yes, does look like other people have grazed this
               | idea as well: https://www.i-programmer.info/programming/j
               | avascript/2380-ja....
        
           | mmcdermott wrote:
           | Clojure Spec works really well for this sort of thing. It
           | doesn't serialize to JSON, but it would be able to check for
           | it.
           | 
           | You could also think about Dhall as a front-end. You could
           | represent the whole credential as a union type. This isn't
           | deeply thought out, but this should give an idea as to how
           | this would look:                   let TestResult = <
           | Positive | Negative >              let ScreeningTestDetails =
           | { hasTestResult : Bool, testResult : TestResult, testTime :
           | Natural }              let CredentialData =               <
           | Vaccinated | RapidSarsCov2PCRTest : ScreeningTestDetails >
           | let Credential =               { credentialName : Text
           | , credentialIssuer : Text               , credentialData :
           | CredentialData               }              let result
           | : Credential             = { credentialName = "COVID-19 Back
           | to Work Credential"               , credentialIssuer = "Acme
           | Labs Inc."               , credentialData =
           | CredentialData.Vaccinated               }              let
           | result2             : Credential             = {
           | credentialName = "COVID-19 Back to Work Credential"
           | , credentialIssuer = "Acme Labs Inc."               ,
           | credentialData =
           | CredentialData.RapidSarsCov2PCRTest                     {
           | hasTestResult = True                     , testResult =
           | TestResult.Negative                     , testTime =
           | 1622145851                     }               }
           | let prop0 =           l(x : ScreeningTestDetails) -
           | assert : greaterThan x.testTime 1522145851 [?] True
           | in  result2
           | 
           | Notice here that the type for credential data can only be
           | vaccinated or a test result. It can't even represent
           | unvaccinated. You could probably take it farther with
           | dependent types and assertions.
           | 
           | Edit: added an assertion to model the 72 hour requirement.
        
           | 0xFACEFEED wrote:
           | Straw man.
           | 
           | With all due respect, you're making a classic mistake:
           | presenting the solution to a problem without tracing the
           | problem back to the use case.
           | 
           | Why do you need to include the logic matrix in the schema? I
           | can promise you that the real world use cases where you'd
           | need to this are virtually non-existent. You wouldn't even do
           | this for some extreme case like Mars rover software.
           | 
           | Your business logic should have a single source of truth. The
           | vast majority of the time you can just write an API for other
           | software to synchronize with.
           | 
           | Otherwise just ship new builds of your software package to
           | the client instead of a new schema. If you need to be modular
           | then use modular primitives such as shared libraries.
           | 
           | Again, there's virtually no real world scenario where you
           | need to ship a _logic schema_ (in any format) to a client.
           | You might as well ship a shared library, importable module, a
           | completely new binary, etc, etc.
        
             | sebmellen wrote:
             | Interoperability is the main reason. We need this data and
             | the evaluation matrix to be portable across different
             | "credential wallets" as part of a standard model for matrix
             | evaluation of Verifiable Credentials (as an extension that
             | we're working on to the existing data model
             | https://www.w3.org/TR/vc-data-model/).
        
               | 0xFACEFEED wrote:
               | You didn't state the use case initially. The context of
               | the discussion is evaluating the value of the approach.
               | What I'm saying is that you can't make that evaluation
               | without stating the use case. Obviously one can think up
               | a scenario where JsonLogic can be useful - that doesn't
               | mean anything.
               | 
               | > Interoperability is the main reason. We need this data
               | and the evaluation matrix to be portable across different
               | "credential wallets" as part of a standard model for
               | matrix evaluation of Verifiable Credentials (see also
               | https://www.w3.org/TR/vc-data-model/).
               | 
               | Representing verification logic in the schema flawed.
               | Just because the W3C publishes a spec doesn't make it
               | good.
               | 
               | So I guess one of the few valid use cases for JsonLogic
               | (or similar) is if your company makes a bad technical
               | decision and you're forced to implement _something_?
        
           | asah wrote:
           | I'm not sure how to express how much I loathe everything
           | about this "solution."
           | 
           | To answer your question, what you have is (effectively) code,
           | and just use a programming language for this, call it a
           | function, give it a name, arguments, test suite and register
           | it as a plugin to your platform. Oh, and documentation,
           | change history, etc.
           | 
           | Seriously - the "overhead" more than pays for itself when 100
           | other yahoos do this nonsense and you end up with data files
           | containing untestable code that breaks when combined with
           | other code, breaks when the platform is changed, etc etc
        
             | sebmellen wrote:
             | Ok, I take your point, but let's say we need to share these
             | credential objects between different systems that do not
             | have prior knowledge of how to evaluate the credential
             | data. Also, let's say we constrain the logic to only allow
             | for evaluation of any given part of the credential data
             | against a binary "pass | fail" matrix.
             | 
             | What is a better way to share this important part of the
             | schema (the matrix) without resorting to letting the
             | "business logic" perform the evaluation? Optimally, any
             | matrix should be able to run against the same business
             | logic for evaluation.
             | 
             | Also, though I understand why you say that, we won't have
             | "100 other yahoos doing this nonsense," and each schema
             | would go through a pretty thorough review process.
        
               | omegaworks wrote:
               | If your business logic doesn't meet the needs of your
               | business without the schema, the schema is a part of your
               | business logic, that should be subjected to a suite of
               | automated tests.
               | 
               | If your concern is the sharability, consider making a
               | library or service that provides the business logic.
        
               | sebmellen wrote:
               | We'd like to be able to include evaluation matrices
               | within credentials as an extension to the _Verifiable
               | Credentials_ standard (see https://www.w3.org/TR/vc-data-
               | model/). Optimally, different libraries and different
               | services will be able to evaluate a credential using the
               | credential's included matrix (i.e. the evaluation matrix
               | should not be reliant on any business logic from any
               | particular party). I can't get too deep into the use-case
               | but having these parts bundled together is important for
               | what we're working on.
        
               | [deleted]
        
             | mvaliente2001 wrote:
             | Sometimes you need to embed an expression interpreter in
             | your application, for example to allow users to define them
             | at runtime. In cases like that one, having a library with a
             | well defined specification could save a lot of time.
        
               | 0xFACEFEED wrote:
               | It's much more likely that the library would do more harm
               | than good.
               | 
               | Libraries tend to cover broader spectrum of use cases
               | than you'd need. Usually that's okay (eg: URL parsing,
               | string manipulation, HTTP client, etc) but in cases like
               | this the logic schema should be as absolutely minimal as
               | possible.
               | 
               | If you're building an interpreter and need an
               | interchangeable format then you can always generate that
               | out of your own bespoke and very constrained format.
        
           | shaunxcode wrote:
           | I cant help but imagine what it would like like in EDN:
           | {...           parsingMatrix          (if (or (=== (var
           | "credentialData.rapidSarsCov2PCRTest.testresult")
           | "negative")                  (=== (var
           | "credentialData.covid19Vaccination.hasVaccination")
           | true))              "valid"              "invalid")}
        
             | sebmellen wrote:
             | I presume jsedn is your library [0]? I was heretofore
             | unaware of EDN, but it looks like a very clean fit for our
             | needs. I will examine this more in depth, thank you.
             | 
             | [0]: https://github.com/shaunxcode/jsedn
        
         | enriquto wrote:
         | > exactly this method in 2004-2006 but with XML.
         | 
         | Of course! JSON is the modern equivalent of XML. In 10 years
         | everybody will mock JSON just like today we mock XML.
        
           | juped wrote:
           | JSON mania has given me an appreciation for XML not having
           | been so bad after all.
        
             | jchw wrote:
             | I like JSON a lot more than XML for what JSON is used for.
             | XML did have some advantages, like more standards for
             | schemas and templating, but the JSON ecosystem has at least
             | decent facsimiles for these facilities. But the real star
             | of the show is the data model: XML is a _markup language_.
             | Jamming data structures into it is awkward. Not so for
             | JSON, which has two aggregate types, a list type and a map
             | type, followed by the usual suspects of primitive types:
             | string, number, boolean, null.
             | 
             | I can implement a full, strict, compliant JSON parser in an
             | afternoon, maybe even less time. It is simple enough to
             | parse that you can even do it in pure C with relative ease.
             | XML is a lot more complex and a lot of implementations
             | skimped pretty hard on the details. I mean I have fond
             | memories of tinyxml2, and if you take apart any app made in
             | the 2000s you have a good chance of finding reference to it
             | (or on Windows-only apps, MSXML3, or on Linux, libxml...)
             | but it certainly let you do a lot of surprising things. I
             | saw a lot of apps doing XML documents with multiple root
             | nodes. And Apple's plist format is a nightmare. It's so
             | easy to fuck up interpreting XML plist, that Apple did, and
             | it lead to one of the more entertaining privilege
             | escalation bugs in iOS history.
             | 
             | I have some fond memories, but I just don't miss XML. :)
        
             | dnautics wrote:
             | I dunno, to me it's pretty clear that JSON has improvements
             | over XML; XML:
             | 
             | - does not entirely make it clear what should go into a tag
             | attribute versus a nested tag
             | 
             | - conversion of those two features into a unified internal
             | datatype can be tricky (for example, this property led to
             | choices that for erlang's xmerl causes a security
             | regression if you are handling user-submitted xml).
             | 
             | - first class support for text inside of a tag is not what
             | you want in 90% of data interchange events, and support for
             | it creates a burden when deserializing.
             | 
             | - it's confusing what should be a text inside a tag versus
             | a tag attribute. Or should that text be parsed into a
             | number? At least JSON is strongly typed, you know what
             | datatype is what just by looking at it.
             | 
             | - because there aren't good "best practices" around it,
             | everyone rolls their XML schemas with their own ideas about
             | what sort of thing should go where.
             | 
             | The major benefit of XML is its obession with
             | schematization means that at least in many case you can
             | grab a schema and figure out an appropriate declarative
             | command to obtain what you want (if you have the right
             | library), but this has basically been conquered in JSONland
             | using JsonSchema/OpenAPI, and stuff like JsonLogic.
        
               | nly wrote:
               | JSON can't express ordering or duplicate fields in a
               | consistent way.
               | 
               | Consider how you'd write these 2 bits of XML in JSON:
               | 
               | <A><B>foo</B><C>bar</C></A>
               | 
               | vs.
               | 
               | <A><B>too</B><C>bar</C><B>uh oh</B></A>
               | 
               | Without a schema, in the first case, how do you determine
               | whether B should be "foo" or ["foo"]? In the second how
               | do you preserve the relative ordering of B #1, C and B
               | #2?
               | 
               | I worked on a project where we had a parse tree that we
               | wanted to serialize out, and for this reason XML was the
               | natural choice.
        
               | dnautics wrote:
               | So this is exactly a symptom of unclarity of the roles
               | that xml causes in the first place. It seems like You're
               | tying using the tags as keys instead of as information
               | _categories_. In json you would make this something like
               | (pardon my lack of quotes, I 'm on mobile):
               | {type: a, of:[{text: too, type: b}, {text: bar, type:
               | c}]}}
        
               | picometer wrote:
               | { "a": [ { "b": "foo" }, { "c": "bar" } ] }
               | 
               | vs.
               | 
               | { "a": [ { "b": "too" }, { "c": "bar" }, { "b": "uh oh" }
               | ] }
        
               | nly wrote:
               | Yes, so in essence:
               | 
               | - Only ever have a single key in each JSON object
               | (treating them as tuples)
               | 
               | - Make all object values arrays.
               | 
               | It makes for some very unnatural looking JSON.
        
               | bokchoi wrote:
               | > - it's confusing what should be a text inside a tag
               | versus a tag attribute. Or should that text be parsed
               | into a number? At least JSON is strongly typed, you know
               | what datatype is what just by looking at it.
               | 
               | JSON's types are pretty anemic compared to the
               | XMLSchema's datatypes[0]. Even it you don't use all of
               | XSD's complex type system, having these basic datatypes
               | is extremely useful and I wish JSON had similar.
               | 
               | [0] https://www.w3.org/TR/xmlschema11-2/
        
               | legulere wrote:
               | - JSON just has UTF-8. XML has encoding madness.
               | 
               | - JSON has just one escape format and all unicode
               | codepoints can be used. XML generally allows only certain
               | unicode codepoints, at some places like element names its
               | further restricted (Quick: Which characters are not
               | allowed? What's the difference between XML 1.0 and 1.1
               | here?). XML escapes at every place differently. In
               | comments you need to escape less than elsewhere. In
               | attributes you can use newlines but they will get
               | normalized to spaces, you have to hex-encode newlines.
               | There's Cdata.
               | 
               | - JSON doesn't have the entity madness with potential
               | security issues.
               | 
               | - JSON doesn't have namespaces that add a lot of
               | complexity with little benefit
        
           | fastball wrote:
           | I dunno, for me JSON will always be better than XML due to it
           | just being nicer to read / work with.
        
             | willseth wrote:
             | You have clearly only ever had to deal with very simple
             | JSON
        
               | goodpoint wrote:
               | This. Once a document is big or complex enough, the
               | benefit of human readability fades away and you are left
               | with a brittle and very slow serialization format.
        
               | fastball wrote:
               | How much slower is JSON serialization than XML
               | serialization?
        
               | goodpoint wrote:
               | Roughly in the same order of magnitude, depending on the
               | implementation.
               | 
               | Light-years away from zero-copy serialization formats.
               | 
               | See https://en.wikipedia.org/wiki/Comparison_of_data-
               | serializati...
               | 
               | Random example:
               | https://google.github.io/flatbuffers/md__benchmarks.html
               | 
               | Speed is not everything: being able to self-describe data
               | structures (without the data) enables generation of
               | parsers, documentation and tests.
               | 
               | Streaming support also matters.
        
               | fastball wrote:
               | Haha nope, I've dealt with JSON files that were deeply
               | nested and in the 100s of MBs.
               | 
               | When you're dealing with complex data, JSON isn't very
               | fun, but XML is still worse.
        
               | gameswithgo wrote:
               | I've worked with Will on a large XML based system. I'll
               | try to briefly describe our workflow. Our company created
               | reference books. Those books ended up both as printed
               | books and as HTML in a web application service people
               | could subscribe too. Various people would create the
               | content, some in WYSIWIG editors, others editing raw html
               | to tag content to give it structure, and tools that fall
               | somewhat in between. XML tags and annotations can do
               | things like indicate where the title is, sub headings,
               | links to other books or content. etc etc.
               | 
               | This annotation structure not only lets us transform the
               | xml into HTML that resembles the physical book via CSS,
               | but also lets us search the content with awareness of
               | what the content is. Simple example, if a search term
               | appears in a title give it more weight.
               | 
               | When a book is done the XML goes off to a printer to
               | become a book, AND into our XML database. A nice feature
               | of which is a lot of our content is in the DB as XML, you
               | ask for a book page and the DB returns the HTML for the
               | page, backend just forwards that HTML to the browser
               | which displays it. ZERO parsing/transformation anywhere
               | once the DB sends it! Just fling the payload at the
               | browser. Super cool at times.
               | 
               | Anyway we all work with these formats differently, some
               | of us never touch the json and xml, some of us only tweak
               | values in config files. Those of us who work with it like
               | that, the only differences between XML and JSON are "how
               | nice are the serialization apis and how fast are they?
               | how big is the payload?"
               | 
               | But when working WITH the format directly there can be
               | more meaningful differences. And the tools that actually
               | exist for the things you are doing may push you towards
               | one format or the other, even if in principle it wouldn't
               | have really mattered.
               | 
               | note: I keep mixing tenses here but this was all in the
               | past, we got bought, don't do any of this anymore!
        
               | willseth wrote:
               | Cool then maybe share your experience wrangling giant
               | complex JSON and why that was the better technical
               | solution over XML.
        
               | linkdd wrote:
               | Please keep your patronizing comment to yourself, or add
               | some arguments to it.
               | 
               | JSON's spec is simpler, and the data are more compact.
               | There are a ton of extremely fast parsers, as well as
               | stream parsers. Many languages support JSON natively
               | making it extra easy for interoperability.
        
               | willseth wrote:
               | Really? Try querying JSON, or transforming it, or
               | validating it. There are fast JSON parsers? Cool, there
               | are fast XML parsers too (that stream). JSON's spec is
               | simpler, it's also more limited. I don't know what your
               | point is. OP claimed XML was "worse" than JSON for large,
               | deeply nested data, and his most compelling argument was
               | "Haha nope." But sure, I'm patronizing. Go police someone
               | else's comments.
        
               | kbenson wrote:
               | > his most compelling argument was "Haha nope."
               | 
               | Pretty sure that was in response to you making
               | assumptions about their experience, not as an answer to
               | the question about what specifically makes them think
               | that, which you only asked afterwards.
               | 
               | This whole chain of comments is a good example of why
               | responding with a dismissive short comment isn't a good
               | idea, even if it feels good to send in the moment.
        
               | willseth wrote:
               | > This whole chain of comments is a good example of why
               | responding with a dismissive short comment isn't a good
               | idea
               | 
               | This is simply inevitable as long as commenters are
               | willing to make broad generalizations about complex
               | topics. And it's hardly unfair to make assumptions about
               | someone's experience when they _do not include it_ along
               | with their highly reductive comment supposedly based on
               | such experience!
        
               | mypalmike wrote:
               | It's just arrays and maps. Regardless of how large or
               | deeply nested json gets, it's always very simple.
        
         | marktolson wrote:
         | I have successfully implemented this exact project in the past.
         | The project allowed for runtime logic modification however
         | tracking states was built into the platform to make debugging
         | simple. As with every other library or framework, JsonLogic is
         | a great tool if you implement it responsibly.
        
         | solidsnack9000 wrote:
         | Maybe it's a kind of having your cake and eating it too:
         | enjoying the flexibility of passing code around and running it
         | with eval, while not having the security, stability and runtime
         | problems implied by eval.
         | 
         | There are limited scopes in which this can work but it seems to
         | be more about the environment or code loader than about the
         | programming language, _per se_ : for example, plugin systems
         | for build tools and servers. The plugin might be isolated by
         | runtime features (like in the JVM) or by processes (as some web
         | servers do, or as Postgres does) but it's not _language
         | features_ that tend to be useful.
         | 
         | Tensorflow models and CSS selectors are both examples of fairly
         | useful plugins that still have limited enough semantics to be
         | sandboxed effectively.
        
         | pydry wrote:
         | It sounds like your language didn't steer clear of Turing
         | completeness.
         | 
         | That's usually how this type of thing goes wrong. I've seen
         | similar things both work and fail for that reason.
         | 
         | This language made it an explicit goal, though.
        
         | jchw wrote:
         | I 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 wrote:
           | Currently 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 wrote:
             | 'Many of life's failures are people who did not realise how
             | close they were to success when they gave up' -- Thomas
             | Edison.
        
               | burnished wrote:
               | said the man who tested something like 6000 different
               | kinds of plant materials as filaments for a light bulb
        
         | commandlinefan wrote:
         | > If you are reading this, and you think it is a good idea
         | 
         | I came to the comment section here hoping that the site was
         | actually a joke...
        
       | asah wrote:
       | please 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 wrote:
       | Can I ask why do we need to embed lisp in JSON, can't we just
       | serialise our lisp to JSON?
        
       | rubyist5eva wrote:
       | I 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.
        
       | arthurcolle wrote:
       | Not 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 wrote:
         | Imagine trying to _configure_ rules in a CMS without touching
         | code. I work at a place that does it. They may... be using
         | this.
        
           | laurent123456 wrote:
           | Hmm... unversioned, untestable code saved in a database. What
           | could go wrong.
        
             | papito wrote:
             | No 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.
        
       ___________________________________________________________________
       (page generated 2021-05-27 23:01 UTC)