Representing logic as data in JSON
If you must implement this using standard JSON, i'd recommend something akin to Lisp's "S-expressions". A condition could be either a plain object, or an array whose first entry is the logical operation that joins them.
For example:
["AND",
{"var1" : "value1"},
["OR",
{ "var2" : "value2" },
{ "var3" : "value3" }
]
]
would represent var1 == value1 AND (var2 == value2 OR var3 == value3)
.
If you prefer brevity over consistency, you could also allow an object to have multiple properties, which would implicitly be joined by an AND. For example, { "a": "b", "c": "d" }
would be equivalent to ["AND", { "a": "b" }, { "c": "d" }]
. But there are cases (like the example) where the former syntax can not faithfully represent the condition as written; you'd need additional trickery like translating the condition or using dummy property names. The latter syntax should always work.
I needed a format that would:
- Support comparisons other than equality.
- Let variables appear in any position, not just be compared to literals.
- Be consistent, terse, secure, and extensible.
So I built up a format I'm calling JsonLogic. A rule is a JSON object, with the operator in the key position, and one or an array of arguments in the value position. (Inspired by Amazon CloudFormation functions.) Any argument can be another rule, so you can build arbitrarily deep logic.
I've also written two parsers for it: JsonLogic for JavaScript and JsonLogic for PHP.
cHao's example would be written as
{ "and", [
{"==", [ {"var" : "var1"}, "value1" ]},
{ "or", [
{"==", [ {"var" : "var2"}, "value2" ]},
{"==", [ {"var" : "var3"}, "value3" ]}
]}
]}
var
here is the operator to get a property of the "data" object, passed along with the "rule" object to the parser, e.g.:
jsonLogic(
{"==", [{"var":"filling"}, "apple"]} // rule, is this pie apple?
{"filling":"apple", "temperature":100} // data, a pie I'm inspecting
);
// true
There are lots more possible operators (greater than, not-equals, in-array, ternary, etc) and both parsers are available on GitHub (with unit tests and documentation).