json-q
v0.1.11
Published
Retrieves values from JSON objects (and JavaScript objects) by css-selector-like query (includes attribute filters and array flattening).
Downloads
24
Maintainers
Readme
json-q
Retrieves values from JSON objects (and JavaScript objects) by css-selector-like query (includes attribute filters and array flattening).
I am not clever enough to use XPath over objects (via jsonpath, jsonata, JSONPath, ObjectPath or DefiantJs), while I like CSS selectors. JSONSelect looks abandoned, json-query looks overcomplicated; so I created more simple query language (inspired by CSS attribute selectors).
Example
const {get} = require('json-q');
const data = {
a:{
b:[
{name:'xxx',c:{d:1}},
{name:'yyy',c:{d:2}}
]
}
};
get(data, "a b[.c.d=1] name"); //=> ['xxx']
API
get(object, selector, opt)
Returns array of all fields of object from any level of nesting that satisfies selector (with expansions via opt).
About selectors:
- "a" means: get value of all fields named "a" from all nested level of given object
- ".a" means: get value of field named "a" from first level of given object (i.e. object["a"])
- "a b" means: get all values of all fields "b", that are nested of field "a", that can be at any level of given object
- ".a.b" means: get field "b", that is direct descendant of field "a" from first level of given object (i.e. object.a.b)
About filters:
- you can add filter of any depth at any level like this: "a.b[x.y=23] c"
- combination of filters "[.x=23][.y=3]" means "items heaving field x=23 AND field y=3"
- you can use [attr] [attr=value] [attr~=value] [attr|=value] [attr^=value] [attr$=value] [attr*=value] [attr=value] - just like CSS attribute filters do
About pseudos:
- do you remember CSS pseudo-classes? All that :focus, :active, :hover etc.? Pretty useless for objects, even :empty and :first-child, but it is a good concept to add user-defined (parameterless) functions.
- you can add it anywhere: "a b:empty.c"
- look at :empty and see the section about expansions
Another thing - I consider array as multiple values of field, so
arrays of arrays become flat, i.e. {a:[[1], [2,3]]} becomes {a:[1, 2, 3]}}
you can not address array items by index, i.e.
var data = {
a:{
b:{
c:[1,2]
}
}
};
get(data, ".a.b.c"); //=> [1,2]
get(data, ".a.b.c.0"); //=> []
var data = {
a:{
b:[
{c:1},
{c:2}
]
}
}
get(data, ".a.b.c"); //=> [1,2] also
Escaping Special Characters
There are no strings now. So if you have special symbols at field names then you should escape it - I mean dot, colon, square brackets and space symbols (i.e. " .:[]").
var data = {
"a:c":{
x:[1,2]
}
};
get(data, "a:c"); //=> Error "Pseudo 'c' not found."
get(data, "a\\:c"); //=> {x:[1, 2]}
Expansions (i.e. opt param at get)
You can add your own filter or pseudo (or re-define existing one). The difference between them is that filter can only filter (obviously) while pseudo can do anything with intermediate result - i.e. delete, add, change (at any depth) objects at result array.
For instance, new filter for [a!=some value]
var d = [{a:{name:1}}, {a:{name:2}}]
var p = "a[name!=1]";
get( d, p, {
operator : {
"!=" : function(complexFieldValue, value){
return true_if_one_is_true(complexFieldValue, value, (a,b)=>{return a!=b;});
},
}
}); // => [{name:2}]
And pseudo for add "abc" string to all fields names at any level (dont ask me what for)
var d = [{a:{b:1}}, {a:{c:2}}]
var p = "a:abc.cabc";
get( d, p, {
pseudo : {
"abc" : function(arrValue){
return arrValue.map(value => {
deep_iterate(value, (_obj) => {
for(var i in _obj) {
if (typeof _obj[i] !== 'object') {
_obj[i+'abc'] = _obj[i];
delete _obj[i];
}
}
});
return value;
})
},
}
}); // => [2]
Browser
Please use index.min.js at browser (IE9+ and other modern browsers)
License
MIT