Documenting deviations from JSONLogic
I'm not currently able to find documentation for where this differs from JSONLogic. It would be nice if in the documentation, such changes were documented. Is this always meant to be backwards compatible/a superset of the original JSONLogic?
For example, I noticed you changed all "var" to "val." Does "var" still work? Will it continue to work? What was the reason for the change?
json-logic-engine is designed to be completely compatible with json-logic-js. However, we've launched a community initiative called "JSON Logic Core" to provide better interoperability between runtimes and fix some flaws with the initial JSON Logic specification.
You can see some of the discussions here:
- https://github.com/orgs/json-logic/discussions/18 (
valspecific proposal) - https://github.com/orgs/json-logic/discussions
And accepted proposals here:
- https://github.com/json-logic/.github/blob/main/ACCEPTED_PROPOSALS.md
I'm pretty strict about trying to maintain backwards compatibility with the tests.json
The main reason for the val vs var thing..
var had a handful of gotchas with the string-path parsing approach. For example, it was difficult to access keys with dots in them, or empty keys.
One idea was to consider some variant of rfc6901 or rfc6901 itself, but this ended up being kinda controversial. The least controversial path seemed to be: "Let's make it hella simple. The path can be specified as an array. Like an AST."
It definitely got rid of any parsing complexity 😄.
var willl not be removed from the runtime any time soon, but will be considered a Legacy JSON Logic operator for the purposes of this implementation :)
Explaining the AST thing a bit better,
{{#each people}}
- {{name}}: {{position.title}}
{{/each}}
Would parse to something like:
{
"cat": [
{
"cat": {
"each": [
{"val": "people"},
{
"cat": [
"- ",
{ "escape": {"val": "name"} },
": ",
{
"escape": { "val": ["position", "title"] }
},
"\n"
]
}
]
}
}
]
}
Where any path traversal / separation is a responsibility of the grammar, and not the AST, so depending on grammar, you're not just mapping one path format to another. 😄
This also makes it simpler to optimize, especially if val did not have deterministic input.
Like:
{ "val": ["arr", { "val": "idx" }] }
(This would be trivial to optimize down to roughly context?.arr?.[context?.idx ?? null] ?? null)
In the past, it'd be written as:
{ "var": [{ "cat": ["arr.", {"var": "idx"}] }] }
And it'd be quite difficult to partially evaluate this to come up with some sort of mapping.