Skip to main content

Extra JSONPath Syntax

New in version 1.3.0

JSON P3 includes some extra, non-standard JSONPath syntax that is disabled by default. Setting the strict option to false when instantiating a JSONPathEnvironment will enable all non-standard syntax.

import { JSONPathEnvironment } from "json-p3";

const env = new JSONPathEnvironment({ strict: false });
values = env.query("$.some.path", data).values();
warning

Non-standard features are subject to change if:

  • conflicting syntax is included in a future JSONPath standard or draft standard.
  • an overwhelming consensus emerges from the JSONPath community that differs from our choices.

The following definitions build on RFC 9535 (license info), while trying to stay true to its JSONPath model. These non-standard selectors are known to break the definition of location and children from RFC 9535.

Key selector

The key selector ~'<name>' selects at most one name from an object member. It is syntactically similar to the standard name selector, with the addition of a tilde (~) prefix.

When applied to a JSON object, the key selector selects the name from a name/value member, if such a member exists, or nothing if it does not exist. This complements the standard name selector, which select the value from a name/value pair.

When applied to an array or primitive value, the key selector selects nothing.

Key selector strings must follow the same processing semantics as name selector strings, as described in section 2.3.2.1 of RFC 9535.

info

The key selector is introduced to facilitate valid normalized paths for nodes produced by the keys selector and the keys filter selector. I don't expect it will be of much use elsewhere.

Syntax

selector             = name-selector /
wildcard-selector /
slice-selector /
index-selector /
filter-selector /
key-selector /
keys-selector /
keys-filter-selector

key-selector = "~" name-selector

child-segment = bracketed-selection /
("."
(wildcard-selector /
member-name-shorthand /
member-key-shorthand))

descendant-segment = ".." (bracketed-selection /
wildcard-selector /
member-name-shorthand /
member-key-shorthand)

member-key-shorthand = "~" name-first *name-char

Examples

Example JSON document
{
"a": [{ "b": "x", "c": "z" }, { "b": "y" }]
}
QueryResultResult PathsComment
$.a[0].~c"c"$['a'][0][~'c']Key of nested object
$.a[1].~cKey does not exist
$..[~'b']"b"
"b"
$['a'][0][~'b']
$['a'][1][~'b']
Descendant, single quoted key
$..[~"b"]"b"
"b"
$['a'][0][~'b']
$['a'][1][~'b']
Descendant, double quoted key

Keys selector

The keys selector (~) selects all names from an object’s name/value members. This complements the standard wildcard selector, which selects all values from an object’s name/value pairs.

As with the wildcard selector, the order of nodes resulting from a keys selector is not stipulated.

When applied to an array or primitive value, the keys selector selects nothing.

The normalized path of a node selected using the keys selector uses key selector syntax.

Syntax

keys-selector       = "~"

Examples

Example JSON document
{
"a": [{ "b": "x", "c": "z" }, { "b": "y" }]
}
QueryResultResult PathsComment
$.a[0].~"b"
"c"
$['a'][0][~'b']
$['a'][0][~'c']
Object keys
$.a.~Array keys
$.a[0][~, ~]"b"
"c"
"c"
"b"
$['a'][0][~'b']
$['a'][0][~'c']
$['a'][0][~'c']
$['a'][0][~'b']
Non-deterministic ordering
$..[~]"a"
"b"
"c"
"b"
$[~'a']
$['a'][0][~'b']
$['a'][0][~'c']
$['a'][1][~'b']
Descendant keys

Keys filter selector

The keys filter selector selects names from an object’s name/value members. It is syntactically similar to the standard filter selector, with the addition of a tilde (~) prefix.

~?<logical-expr>

Whereas the standard filter selector will produce a node for each value from an object’s name/value members - when its expression evaluates to logical true - the keys filter selector produces a node for each name in an object’s name/value members.

Logical expression syntax and semantics otherwise match that of the standard filter selector. @ still refers to the current member value. See also the current key identifier.

When applied to an array or primitive value, the keys filter selector selects nothing.

The normalized path of a node selected using the keys filter selector uses key selector syntax.

Syntax

filter-selector     = "~?" S logical-expr

Examples

Example JSON document
[{ "a": [1, 2, 3], "b": [4, 5] }, { "c": { "x": [1, 2] } }, { "d": [1, 2, 3] }]
QueryResultResult PathsComment
$.*[~?length(@) > 2]"a"
"d"
$[0][~'a']
$[2][~'d']
Conditionally select object keys
$.*[~?@.x]"c"$[1][~'c']Existence test
$[~?(true == true)]Keys from an array

Current key identifier

# is the current key identifier. # will be the name of the current object member, or index of the current array element. This complements the current node identifier (@), which refers to a member value or array element, respectively.

It is a syntax error to follow the current key identifier with segments, as if it were a filter query.

When used as an argument to a function, the current key is of ValueType, and outside a function call it must be compared.

Syntax

comparable             = literal /
singular-query / ; singular query value
function-expr / ; ValueType
current-key-identifier


function-argument = literal /
filter-query / ; (includes singular-query)
logical-expr /
function-expr /
current-key-identifier

current-key-identifier = "#"

Examples

Example JSON document
{ "abc": [1, 2, 3], "def": [4, 5], "abx": [6], "aby": [] }
QueryResultResult PathComment
$[?match(#, '^ab.*') && length(@) > 0 ][1,2,3]
[6]
$['abc']
$['abx']
Match on object names
$.abc[?(# >= 1)]2
3
$['abc'][1]
$['abc'][2]
Compare current array index