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 = ; const data = a: b: name:'xxx'c:d:1 name:'yyy'c:d:2 ; ; //=> ['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:12 ; ; //=> [1,2]; //=> [] var data = a: b: c:1 c:2 ; //=> [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:12 ; ; //=> Error "Pseudo 'c' not found."; //=> {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:2var p = "a[name!=1]"; ; // => [{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:2var p = "a:abc.cabc"; ; // => [2]
Browser
Please use index.min.js at browser (IE9+ and other modern browsers)
License
MIT