json-logic-js
json-logic-js copied to clipboard
Any thoughts on Javascript -> json logic conversion?
I believe it should be possible to programmatically serialize a subset of Javascript (a function that returns a Number or Boolean and contains no loops or external function calls) into json logic, no?
This would make storing and sandboxed execution of simple things nice.
Any thoughts before I begin work?
I can't quite visualize it. Could you show me some pseudocode what you'd like to be able to accomplish with it?
const isEvenJS = `(num) => num % 2 == 0` // this could come from a user as well
const isEvenJSON = proposedModule.serialize(isEvenJS)
console.log(isEvenJSON)
// prints {"==": [{"%": [{"var":"num"}, 2]}, 0]}
You'd traverse the AST produced by Babel or another parser and convert it to JSON Logic
WOW. That would be cool. Having never worked on a parser before, I was happy to just hand write things into a syntax tree, but there sure are cases where just writing something in JavaScript syntax, then storing, transmitting, or manipulating it as JSON would be awesome.
I can think of two examples I've heard of subsetting JavaScript: Doug Crockford's AdSafe subset and I know John Resig is doing some neat things at Khan Academy but I can't find the article I dimly remember from ~5 years ago where he talks about neat tricks using the with
statement...
I wonder if variable reference is going to need to get more sophisticated than the current implementation of var
. E.g., in the trivial example I'm not clear in my own mind whether "num," as a formal parameter, should be obfuscated or normalized in some way that clearly differentiates it from "num" as a property on the expected data object. Trivial example doesn't need to care, but is that sustainable?
A different trivial example that plays to JsonLogic's current strengths might be:
const isEvenJS = `data.num % 2 === 0` // this could come from a user as well
const isEvenJSON = proposedModule.serialize(isEvenJS)
console.log(isEvenJSON)
// prints {"===": [{"%": [{"var":"num"}, 2]}, 0]}
Where serialize is cool with properties and array indices on data
, but consistently forbids things like num
or window.location
My understanding from the documentation is that data that is not object-like (objects + arrays) cannot be a parameter to apply – so for example some logic.apply(rules, 4)
is prohibited. If my understanding is correct, I will be sure to preserve that requirement when parsing input Javascript (the function cannot access the parameter directly, but must access either a property or index).
Is there a reason, however, you decided against logic.apply(rules, 4)
cases? I suppose it would require a reserved parameter name like input
or data
or something which could make things tricky.
And yeah, I'm pretty sure any JS serialized would either fail or be safe since any non-safety either requires some global variable access (will fail) or a while (1) {}
style thing which will also fail
Ideas for simple names for this companion library? js-to-json-logic
feels a bit wordy
I just haven't had a case where I needed something like logic.apply(rules, 4)
in production. I suspect it would be easy to modify var
so this worked:
jsonLogic.apply({"var":""}, 4) // want to return 4
(I'm a little surprised it doesn't accidentally work, based on how I remember implementing the dot-notation code)
Would js2json
be a reasonable library name?
Turns out js2json
is taken on NPM: https://www.npmjs.com/package/js2json
This is a really interesting topic, hope we can get it done!
Is this being worked on? I'm asking it because recently I implemented something similar (but with fewer operations for now). The user can input a data
and a logic
using infix notation. Then I convert the infix logic
to a proper JSON
and display it for the user. I also show the result of the logic
being applied to the data
for debuging reasons. Below are some screenshots of what I've got:
-
Simple multiplication:
-
Maps the [1,2,3] array to [2,4,6], filters to get only [4,6] and reduces it to (6*(4*(0+1)+1))
With what I have, I currently support the following operators (ordered by precedency):
*
, /
, %
;
+
, -
, cat
, in
, substr
;
===
, !==
, ==
, !=
, <
, >
, <=
, >=
, or
, and
;
?
followed by :
, filter
, map
, reduce
followed by initial
, method
followed by arguments
.
With my approach, only if
, reduce
and method
are currently supporting three arguments. The rest uses only 2. I'm also parsing arrays, objects, and strings (but only strings that don't contain any spaces for now); the rest are treated as variables. E.g:
Is there any interest on joining this with jsonLogic? Has anyone started anything similar?
@lucas2595 that looks great! I think it's very close to what the OP was proposing. It would be amazing if you could share your code.
@felix-last here you go: https://github.com/lucas2595/js2jl
@lucas2595 great, thank you! I will look into it and see if our use case may yield some PRs as well.
I managed to build a Node.js module that uses Babel to parse JavaScript expressions and then turn the AST into into JSON Logic rules. Repo here: https://github.com/krismuniz/js-to-json-logic
Is there any package that can covert functions in JS to JSON Logic?