
Security News
Browserslist-rs Gets Major Refactor, Cutting Binary Size by Over 1MB
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
gson-query
Advanced tools
Query and transform your json data using an extended glob-pattern within browsers or nodejs
Query and transform your json data using an extended glob-pattern. This is a really helpful tool to quickly
- fuzzy search json-data matching some search properties
- transform data with consistent structures
- extract information from json-data
npm install gson-query --save
and get it like
const query = require("gson-query");
The command-line integration can be installed separately by gson-query-cli
v3.0.0
(2019/09/26)
#
, #/
, /
) no callback root object with (rootObject, null, null, "#")
v2.0.0
a negated filter (lookahead), e.g. *?valid:!true
will not return objects where valid === undefined
. To match objects with missing properties you can still query them explicitly with *?valid:!true||valid:undefined
run a callback-function on each match of your query
query.run(data, "/server/*/services/*", callback);
a callback receives the following arguments
/**
* @param {Any} value - value of the matching query
* @param {String} key - the property or index of the value
* @param {Object|Array} parent - parent[key] === value
* @param {String} jsonPointer - json-pointer in data, pointing to value
*/
function callback(value, key, parent, jsonPointer) => { /* do sth */ }
get matches in an array instead of running a callback
let results = query.get(data, "/server/*?state:critical", query.get.VALUE); // or POINTER or ALL
which is the same as
let results = query.get(data, "/server/*/services/*", (value) => value);
or quickly delete properties from your data
query.delete(data, "/server/*/services/{szm-.*}");
Use patterns to query patterns recursively
query.pattern(data, "/node(/nodes/*)+/value");
and to select multiple properties of an object or array:
query.pattern(data, "/server((/store), (/{front-.*}))/services/*");
All examples import const query = require("gson-query");
At first, json-query acts like a normal json-pointer
let data = {
"parent": {
"child": { "id": "child-1" }
}
};
const result = query.get(data, "#/parent/child/id", query.get.VALUE);
// result:
[
"child-1"
]
But query also supports glob-patterns with *
:
let data = {
"parent": {
"child": { "id": "child-1" }
},
"neighbour": {
"child": { "id": "child-2" }
}
};
const result = query.get(data, "#/*/child/id", query.get.VALUE);
// result:
[
"child-1",
"child-2"
]
and glob-patterns with **
:
let data = {
"parent": {
"id": "parent",
"child": {"id": "child-1"}
},
"neighbour": {
"child": {"id": "child-2"}
}
};
const result = query.get(data, "#/**/id", query.get.VALUE);
// result:
[
"parent",
"child-1",
"child-2"
]
or simply call query.get(data, "#/**", query.get.VALUE)
to query the value of each property
let data = {
"parent": {
"id": "parent",
"child": { "id": "child-1" }
}
};
const result = query.get(data, "#/**/id", query.get.VALUE);
// result:
[
{
"id":"parent",
"child": { "id":"child-1" }
},
"parent",
{ "id":"child-1" },
"child-1"
]
To filter the matched objects, an object-query string may be appended on each single step:
let data = {
"parent": {
"valid": true,
"child": {"id": "child-1"}
},
"neighbour": {
"valid": false,
"child": {"id": "child-2"}
},
"dungeons": {
"child": {"id": "child-3"}
}
};
let result = query.get(data, "#/**?valid:true&&ignore:undefined/child", query.get.VALUE);
// same result with
result = query.get(data, "#/**?valid:!false/child", query.get.VALUE);
// result:
[
{
"valid": true,
"child": {"id": "child-1"}
}
]
or match all objects that have a defined property valid like query.run(data, "#/**?valid", callback)
.
let data = {
"parent": {
"valid": true,
"child": {"id": "child-1"}
},
"neighbour": {
"valid": false,
"child": {"id": "child-2"}
},
"dungeons": {
"child": {"id": "child-3"}
}
};
const result = query.get(data, "#/**?valid", query.get.VALUE);
// result:
[
{
"valid": true,
"child": {
"id": "child-1"
}
},
{
"valid": false,
"child": {
"id": "child-2"
}
}
]
regular expression must be wrapped with {.*}
:
let data = {
"albert": {valid: true},
"alfred": {valid: false},
"alfons": {valid: true}
};
const result = query.get(data, "#/{al[^b]}?valid:true", query.get.POINTER);
// result:
[
"#/alfred"
]
If you want a callback on each match use query.run(data:object|array, query:string, callback:function):void
query.run(data, "#/**/*?valid", (value, key, parent, jsonPointer) => {});
Each callback has the following signature
callback(value:any, key:string, parent:object|array, jsonPointer:string)
/**
* @param {Any} value - value of the matching query
* @param {String} key - the property or index of the value
* @param {Object|Array} parent - parent[key] === value
* @param {String} jsonPointer - json-pointer in data, pointing to value
*/
function callback(value, key, parent, jsonPointer) => { /* do sth */ }
If you only require values or pointers, use query.get(data:object|array, query:string, type:TYPE = "all")
to receive an Array or Object as result
// default: query.get.VALUES
let arrayOfValues = query.get(data, "#/**/id", query.get.VALUE);
// result: [value, value]
let arrayOfJsonPointers = query.get(data, "#/**/id", query.get.POINTER);
// result: ["#/..", "#/..", ...]
let arrayOfAllFourArguments = query.get(data, "#/**/id", query.get.ALL);
// result: [arguments, arguments], where arguments = 0:value 1:object 2:key 3:jsonPointer
let mapOfPointersAndData = query.get(data, "#/**/id", query.get.MAP);
// result: {"#/..": value, "#/..": value}
let mapOfPointersAndData = query.get(data, "#/**/id", (val, key, parent, pointer) => `custom-${pointer}`);
// result: ["custom-#/parent/child/id", "custom-#/neighbour/child/id", "custom-#/dungeons/child/id"]
Multiple items on objects or in arrays may also be delete with query.delete(data:object|array, query:string):void
:
query.delete(data, "#/**/*/data");
The pattern-queries behave as the default query.get
methods:
import query from "gson-query";
// predefined callback
const targets = query.pattern(data, "#/*(/node/*?valid)+/valid", query.get.POINTER); // return pointers
const values = query.pattern(data, "#/*(/node/*?valid)+/valid", query.get.VALUES); // return values
// ...
// custom callback
query.pattern(data, "#/*(/node/*?valid)+/valid", (value, key, parent, jsonPointer) => {});
Pattern-queries enable selection of recursive patterns and offer a way to build up a collection of data for further filterung. A pattern uses brackets ()
to identify repeatable structures and offers multiple selections for the same data-entry.
Using a pattern-query like #/tree((/left),(/right))*
will recursively select all left and right-nodes. e.g.
const data = {
tree: {
left: {
id: "1",
left: { id: "2" },
right: { id: "3" }
},
right: {
id: "4"
}
}
};
const result = query.pattern(data, "#/tree((/left),(/right))*/id");
// ["1", "2", "3", "4"]
Note that each pattern-queries are resovled using query.get
and thus support all mentioned features.
One use-case for pattern-queries can be found in json-schema specification. Any definition in #/defs
may reference itself or be referenced circular. A linear query cannot describe the corresponding data, but pattern-queries might be sufficient.
A pattern is a simple group defined by brackets: #/a(/b)/c
, which is identical to #/a/b/c
. But a group may also have a quantifier +
: #/a(/b)+/c
. Using a quantifier, the query within the pattern will be applied as long as it matches any data. Its combined result will then be passed to /c
.
e.g. applying the pattern #/a(/b)+/c
on the following input data:
const input = {
a: {
b: {
c: "1",
b: {
c: "2",
b: {}
}
}
}
};
will first select property a
and then repeatedly select property b
: [a/b, a/b/b, a/b/b/b]
. This result is filtered by c
, which will return ["1", "2"]
(the last b
-object has no property c
).
Patterns can also be used for OR-operations. An OR is identified by a semicolon ,
and must be within and between patterns, like ((/a/b),(/c))
. Not valid patterns are (/a/b, /c) and r/(/a/b),(/c)/f.
Currently, using OR is commutative in a sense that ((/a),(/b)) = ((/b),(/a))
, (with a different ordering of the resulting set), distributive so that /a((/b), (/c)) = ((/a/b), (/a/c))
. Parenthesis without a quantifier are associative, e.g. #/a/b/c = #/a(/b)/c = #/a(/b/c) = #/a(/b)(/c)
. Thus, a pattern ((/b)(/c))+
can also be written like (/b/c)+
.
for further examples refer to the unit tests
FAQs
json-pointer utilities for querying and transforming data
The npm package gson-query receives a total of 563 weekly downloads. As such, gson-query popularity was classified as not popular.
We found that gson-query demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
Research
Security News
Eight new malicious Firefox extensions impersonate games, steal OAuth tokens, hijack sessions, and exploit browser permissions to spy on users.
Security News
The official Go SDK for the Model Context Protocol is in development, with a stable, production-ready release expected by August 2025.