-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is it possible to use JSONLogic as a query language? #15
Comments
You could do this by combining JavaScript's filter with that rule: data.filter(function(item){
return jsonLogic.apply(filter, item);
}) You could also monkey-patch this onto the library quickly like: jsonLogic.filter = function(rule, data){
if(typeof data.filter !== "function"){
throw "jsonLogic.filter requires data be an Array";
}
return data.filter(function(item){
return jsonLogic.apply(rule, item);
});
}; By the way, there's a special three-argument syntax for { "or": [
{ "<=": [ 3, { "var": "id" }, 5 ] },
{ ">": [ { "var": "id" }, 7 ] }
] }; I hesitate to bake this into the spec, just because I don't have time right now to write appropriate unit tests for it. Does this get you where you need to go? |
Works like a charm! You can test and compare different JSON query languages online at http://jsonquerytool.com. Looks like JSON Logic can be used as a good alternative to them, because 1) the rule of query can be so complex as I want and 2) the query is a JSON itself. I want to create a server that uses only JSON for everything: JSON database, JSON API (JSON Logic for query language and JSON Patch for sync changes between client and server), JSON Schema (http://json-schema.org) for validating submitted data and describing API. Not sure that there is a ready solution that uses all these things together. Have you heard anything about JSON Patch (http://jsonpatch.com)? I'm very inspired by JSON Patch idea, but seems the syntax might be easier and cleaner in prefix notation and without [
{"replace": [{"path": "/baz"}, {"value": "boo"}]},
{"add": [{"path": "/hello"}, {"value": "world"}]},
{"remove": {"path": "/foo"}}
] or even: [
{"replace": ["/baz", "boo"]},
{"add": ["/hello", "world"]},
{"remove": "/foo"}
] instead of patch: [
{"op": "replace", "path": "/baz", "value": "boo"},
{"op": "add", "path": "/hello", "value": "world"},
{"op": "remove", "path": "/foo"}
] The original JSON document: {
"baz": "qux",
"foo": "bar"
} The result: {
"baz": "boo",
"hello": "world"
} And looks like JSON Logic can be used instead of JSON Pointer to specify the parts of the document to operate on. BTW, seems the syntax of JSON Logic might be also easier and cleaner without var rules =
{
"and": [
{"<": ["temp", 110]},
{"==": ["pie.filling", "apple"]}
]
}; instead of: var rules =
{
"and": [
{"<": [{"var": "temp"}, 110]},
{"==": [{"var": "pie.filling"}, "apple"]}
]
}; var data =
{
"temp": 100,
"pie": {
"filling": "apple"
}
}; jsonLogic.apply(rules, data);
// true What do you think about all this? |
I think you're right, you could pretty quickly patch in I'm not familiar with JsonPointer, but I have used dotty--I just suggested a way to mooch functionality off that library into JsonLogic rules in this issue. Re: cleaner syntax without var, in your example how does the parser understand that "temp" and "pie.filling" are data names, but "apple" is a literal string? It's totally doable in a command like |
There are 2 possible ways: The first (not recommended because limits the flexibility):
The second:
Why I raised the issue of easier and cleaner syntax? What do you think about the syntax of https://npmjs.com/package/json-logic? It also uses |
What about What about sorting (ordering) JSON? |
from data:
?
from data:
? |
@jwadhams, any ideas? |
The title of the issue caught my attention. I really like JSON Logic. It seems incredibly powerful. I think the issue described here: #116 and the related PR could make the objective of this ticket far easier. Assuming the function json_filter(logic, data, jsonlogic) {
return data.filter(function(item){
// NOTE: the proposed implementation of traverse gives us back an array, so we de-array-ify it.
return jsonlogic.apply(logic, item)[0];
});
};
jsonLogic.add_operation('json_filter', (logic, data, jsonlogic) => {
return json_filter(logic, data, jsonlogic);
}, {
traverse: false
}); Then, I did the following: Expand to view example jsonLogic.applyjsonLogic.apply(
{"json_filter":{"or":[{"<=":[3,{"var":"id"},5]},{">":[{"var":"id"},7]}]}},
[
{
"id": 1,
"name": "Oliver",
"email": "[email protected]"
},
{
"id": 2,
"name": "Jack",
"email": "[email protected]"
},
{
"id": 3,
"name": "Harry",
"email": "[email protected]"
},
{
"id": 4,
"name": "Jacob",
"email": "[email protected]"
},
{
"id": 5,
"name": "Charlie",
"email": "[email protected]"
},
{
"id": 6,
"name": "Thomas",
"email": "[email protected]"
},
{
"id": 7,
"name": "George",
"email": "[email protected]"
},
{
"id": 8,
"name": "Oscar",
"email": "[email protected]"
},
{
"id": 9,
"name": "James",
"email": "[email protected]"
},
{
"id": 10,
"name": "William",
"email": "[email protected]"
}
]
); Results: [
{
"id": 3,
"name": "Harry",
"email": "[email protected]"
},
{
"id": 4,
"name": "Jacob",
"email": "[email protected]"
},
{
"id": 5,
"name": "Charlie",
"email": "[email protected]"
},
{
"id": 8,
"name": "Oscar",
"email": "[email protected]"
},
{
"id": 9,
"name": "James",
"email": "[email protected]"
},
{
"id": 10,
"name": "William",
"email": "[email protected]"
}
] Pretty cool! And, one more thing for kicks that is only tangentially related. I had the same thought regarding JSON Patch! It would be neat to be able to leverage JSON Patch within JSON Logic. Well, you could do such a thing! I'm attaching an example. Expand to see JSON Patch exampleimport * as jsonPatch from 'fast-json-patch';
function applyPatch(logic, data, jsonlogic) {
return jsonPatch.applyOperation(data, logic[0]).newDocument;
}
jsonLogic.add_operation('jsonPatch.applyPatch', applyPatch, {
traverse: false
});
jsonLogic.apply(
{"jsonPatch.applyPatch":[{"op":"replace","path":"/0/id","value":"99"}]},
// the data from earlier
); Results: [
{
"id": "99",
"name": "Oliver",
"email": "[email protected]"
}, All that to say, if the |
Is it possible to use JSONLogic as a query language to filter JSON? Something like this:
It should return:
The text was updated successfully, but these errors were encountered: