You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hey; awesome work on your Rust implementation of JSON Logic! We communicated briefly on this guy: jwadhams/json-logic#46 And I saw your Reddit post!
I've been trying to get a hold of the creator of JSON Logic for a few years now (publicly: jwadhams/json-logic-js#119), and privately.
I wanted to recommend / list a few common modifications that I believe make JSON Logic a bit more powerful.
Namely:
Dot-Prop Notation
Imagine you have the following data,
{ "a.b": { "c": 5 } }
With the current spec, you're unable to access c easily.
JSON-Logic-Engine (and a few other JSON Logic implementations) implement a backwards compatible extension that allows you to escape the dots, fetching it with { "var": "a\\.b.c" }
This one is more exotic and specific to only my implementation of JSON Logic.
One common issue in JSON Logic is that in iterators / control structures, it's currently impossible in most engines to fetch context from outside the iterator.
The way I resolved it was by adding ../ support to the var method, which allows it to crawl up to above context.
I have it set up so that inside map and other iterators, going one layer up gives you access to the iterable and the index (../index), and going up two layers gives you access to whatever context (../../) invoked the iterator, so on and so forth.
(Perhaps Not Applicable To DataLogic-RS) Enabling / Disabling Automatic Traversal of Logic
This isn't really a spec thing, more an engine impl thing,
One of the issues with many of the JSON Logic implementations is that some of the control structure operators are "special" / programmed in a special way compared to user land operators,
So it's impossible for someone to add their own map or if method in json-logic-js, because the logic is automatically traversed and executed.
I worked around this in json-logic-engine by allowing users to specify traverse: false when adding a method, which tells the logic engine "Hey! This method is responsible for handling the execution of the logic; it'll decide on its own to call the apply method for the arguments"
It seems to me that your package takes the opposite approach of most other engines (this is not a gripe!) and expects all operators to handle their own arguments. So instead of being traverse: true like most engines, this package is traverse: false by default.
If you did decide to add a traverse setting, it might simplify the programming for some of the methods, and get rid of a handful of the apply calls.
"Preserve" / "Get" / Specifying Data vs Logic
This really only makes sense in engines that have traversal flags, but in JLE you're able to use preserve to embed data in your logic, and avoid having it executed, like so: { "preserve": { "name": "John", "age": 27 } }.
This makes it easier to pass complex data into your methods.
One common issue in the JSON Logic world is figuring out how to embed data, and different engines have different rules for deciding "This is logic" vs "This is data".
In JLE, I allow you to override the isData method to configure it, so you can specify: "Hey, this guy has >1 keys, so it's data instead of logic". There's also a permissive mode that will keep the object as data if it does not match a method registered in the engine.
This is an ambiguity in the spec I think needs worked out. I've seen it pop up in a few other projects
There are some other things, but they're just not the same in Rust
Async stuff notably.
My goal for highlighting some of this is that I think there are some impl differences between engines and ambiguities that need resolved, and some common issues that I think the community could resolve if a spec was discussed and potentially voted upon.
For example:
I think the dotprop notation is a simple, backwards compatible tweak that would resolve a common issue I see pop up in different ecosystems.
I think it'd be good for the community to figure out a way to access context outside of iterators. While I like the Handlebars/Directory notation for that, I think it should be discussed.
And basically, my desire is to start a dialog between different maintainers to try to get some of the ambiguous and problematic parts of JSON Logic resolved, and maybe we could get a compatibility repo / GitHub org going that lists some of the adopted extensions.
As you've built one of the newest JSON Logic implementations, I'd figure I'd start by reaching out and seeing if there was any interest in collaborating?
I'd love to get Jeremy involved, but I've had some difficulty reaching him (he's busy, I'm sure).
Tangentially Related:
I use JSON Logic for a handful of projects, and use it as an AST for some grammars I've put together over the years to simplify development (it's pretty good for setting up filters and translating queries and setting up password rules). One recent use case was converting handlebars templates into JSON Logic: Support for eval-less template execution handlebars-lang/handlebars.js#1934 (comment)
Am 100% happy to collaborate on this. Also, as I'm new to JSONLogic, I'm perfectly fine to follow what you have already thought through. Please feel free to suggest changes and don't hesitate to request for some contributions. I would love to add more test cases for these new cases to start with.
Hey; awesome work on your Rust implementation of JSON Logic! We communicated briefly on this guy: jwadhams/json-logic#46 And I saw your Reddit post!
I've been trying to get a hold of the creator of JSON Logic for a few years now (publicly: jwadhams/json-logic-js#119), and privately.
I wanted to recommend / list a few common modifications that I believe make JSON Logic a bit more powerful.
Namely:
Dot-Prop Notation
Imagine you have the following data,
With the current spec, you're unable to access
c
easily.JSON-Logic-Engine (and a few other JSON Logic implementations) implement a backwards compatible extension that allows you to escape the dots, fetching it with
{ "var": "a\\.b.c" }
Relevant issue: json-logic/json-logic-engine#23
Handlebars Style Data Traversal
This one is more exotic and specific to only my implementation of JSON Logic.
One common issue in JSON Logic is that in iterators / control structures, it's currently impossible in most engines to fetch context from outside the iterator.
See:
The way I resolved it was by adding
../
support to thevar
method, which allows it to crawl up to above context.I have it set up so that inside
map
and other iterators, going one layer up gives you access to the iterable and the index (../index
), and going up two layers gives you access to whatever context (../../
) invoked the iterator, so on and so forth.(Perhaps Not Applicable To DataLogic-RS) Enabling / Disabling Automatic Traversal of Logic
This isn't really a spec thing, more an engine impl thing,
One of the issues with many of the JSON Logic implementations is that some of the control structure operators are "special" / programmed in a special way compared to user land operators,
So it's impossible for someone to add their own
map
orif
method in json-logic-js, because the logic is automatically traversed and executed.I worked around this in json-logic-engine by allowing users to specify
traverse: false
when adding a method, which tells the logic engine "Hey! This method is responsible for handling the execution of the logic; it'll decide on its own to call the apply method for the arguments"It seems to me that your package takes the opposite approach of most other engines (this is not a gripe!) and expects all operators to handle their own arguments. So instead of being
traverse: true
like most engines, this package istraverse: false
by default.If you did decide to add a traverse setting, it might simplify the programming for some of the methods, and get rid of a handful of the apply calls.
"Preserve" / "Get" / Specifying Data vs Logic
This really only makes sense in engines that have traversal flags, but in JLE you're able to use
preserve
to embed data in your logic, and avoid having it executed, like so:{ "preserve": { "name": "John", "age": 27 } }
.This makes it easier to pass complex data into your methods.
One common issue in the JSON Logic world is figuring out how to embed data, and different engines have different rules for deciding "This is logic" vs "This is data".
In JLE, I allow you to override the
isData
method to configure it, so you can specify: "Hey, this guy has >1 keys, so it's data instead of logic". There's also apermissive
mode that will keep the object as data if it does not match a method registered in the engine.See:
This is an ambiguity in the spec I think needs worked out. I've seen it pop up in a few other projects
There are some other things, but they're just not the same in Rust
My goal for highlighting some of this is that I think there are some impl differences between engines and ambiguities that need resolved, and some common issues that I think the community could resolve if a spec was discussed and potentially voted upon.
For example:
And basically, my desire is to start a dialog between different maintainers to try to get some of the ambiguous and problematic parts of JSON Logic resolved, and maybe we could get a compatibility repo / GitHub org going that lists some of the adopted extensions.
As you've built one of the newest JSON Logic implementations, I'd figure I'd start by reaching out and seeing if there was any interest in collaborating?
I'd love to get Jeremy involved, but I've had some difficulty reaching him (he's busy, I'm sure).
Tangentially Related:
I support JSON Logic because I feel it's a pretty simple, portable spec that resolves this issue that I see come up a ton - https://x.com/thdxr/status/1796338513165611080
But I think it could be a bit stronger if there was a bit more of a connected & collaborative ecosystem
The text was updated successfully, but these errors were encountered: