2.5. Segments
2.5. Segments
For each node in an input nodelist, segments apply one or more selectors to the node and concatenate the results of each selector into per-input-node nodelists, which are then concatenated in the order of the input nodelist to form a single segment result nodelist.
It turns out that the more segments there are in a query, the greater the depth in the input value of the nodes of the resultant nodelist:
- A query with N segments, where N >= 0, produces a nodelist
consisting of nodes at depth in the input value of N or greater.
- A query with N segments, where N >= 0, all of which are child
segments (Section 2.5.1), produces a nodelist consisting of nodes precisely at depth N in the input value.
There are two kinds of segments: child segments and descendant segments.
segment = child-segment / descendant-segment
The syntax and semantics of each kind of segment are defined below.
2.5.1. Child Segment
2.5.1.1. Syntax
The child segment consists of a non-empty, comma-separated sequence of selectors enclosed in square brackets.
Shorthand notations are also provided for when there is a single wildcard or name selector.
child-segment = bracketed-selection /
("."
(wildcard-selector /
member-name-shorthand))
bracketed-selection = "[" S selector *(S "," S selector) S "]"
member-name-shorthand = name-first *name-char
name-first = ALPHA /
"_" /
%x80-D7FF /
; skip surrogate code points
%xE000-10FFFF
name-char = name-first / DIGIT
DIGIT = %x30-39 ; 0-9
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
., a child-segment directly built from a wildcard-selector, is shorthand for [].
.
2.5.1.2. Semantics
A child segment contains a sequence of selectors, each of which selects zero or more children of the input value.
Selectors of different kinds may be combined within a single child segment.
For each node in the input nodelist, the resulting nodelist of a child segment is the concatenation of the nodelists from each of its selectors in the order that the selectors appear in the list. Note: Any node matched by more than one selector is kept as many times in the nodelist.
Where a selector can produce a nodelist in more than one possible order, each occurrence of the selector in the child segment may produce a nodelist in a distinct order.
In summary, a child segment drills down one more level into the structure of the input value.
2.5.1.3. Examples
JSON:
["a", "b", "c", "d", "e", "f", "g"]
Queries:
| Query | Result | Result | Comment |
|---|---|---|---|
| Paths | |||
| $[0, | "a" | $[0] | Indices |
| 3] | "d" | $[3] | |
| $[0:2, | "a" | $[0] | Slice and |
| 5] | "b" | $[1] | index |
| "f" | $[5] | ||
| $[0, | "a" | $[0] | Duplicated |
| 0] | "a" | $[0] | entries |
Table 15: Child Segment Examples
2.5.2. Descendant Segment
2.5.2.1. Syntax
The descendant segment consists of a double dot .. followed by a child segment (using bracket notation).
Shorthand notations are also provided that correspond to the shorthand forms of the child segment.
descendant-segment = ".." (bracketed-selection /
wildcard-selector /
member-name-shorthand)
.., the descendant-segment directly built from a wildcard-selector, is shorthand for ..[].
..
Note: On its own, .. is not a valid segment.
2.5.2.2. Semantics
A descendant segment produces zero or more descendants of an input value.
For each node in the input nodelist, a descendant selector visits the input node and each of its descendants such that:
-
nodes of any array are visited in array order, and
-
nodes are visited before their descendants.
The order in which the children of an object are visited is not stipulated, since JSON objects are unordered.
Suppose the descendant segment is of the form ..[<selectors>] (after converting any shorthand form to bracket notation), and the nodes, in the order visited, are D1, ..., Dn (where n >= 1). Note: D1 is the input value.
For each i such that 1 <= i <= n, the nodelist Ri is defined to be a result of applying the child segment [<selectors>] to the node Di.
For each node in the input nodelist, the result of the descendant segment is the concatenation of R1, ..., Rn (in that order). These results are then concatenated in input nodelist order to form the result of the segment.
In summary, a descendant segment drills down one or more levels into the structure of each input value.
2.5.2.3. Examples
JSON:
{
"o": {"j": 1, "k": 2},
"a": [5, 3, [{"j": 4}, {"k": 6}]]
}
Queries:
(Note that the fourth example can be expressed in two equivalent queries, shown in Table 16 in one table row instead of two almost- identical rows.)
| Query | Result | Result Paths | Comment |
|---|---|---|---|
| $..j | 1 | $['o']['j'] | Object values |
| 4 | $['a'][2][0]['j'] | ||
| $..j | 4 | $['a'][2][0]['j'] | Alternative |
| 1 | $['o']['j'] | result | |
| $..[0] | 5 | $['a'][0] | Array values |
| {"j": 4} | $['a'][2][0] | ||
| $..[*] | {"j": 1, | $['o'] | All values |
| or | "k": 2} | $['a'] | |
| $..* | [5, 3, | $['o']['j'] | |
| [{"j": 4}, | $['o']['k'] | ||
| {"k": 6}]] | $['a'][0] | ||
| 1 | $['a'][1] | ||
| 2 | $['a'][2] | ||
| 5 | $['a'][2][0] | ||
| 3 | $['a'][2][1] | ||
| [{"j": 4}, | $['a'][2][0]['j'] | ||
| {"k": 6}] | $['a'][2][1]['k'] | ||
| {"j": 4} | |||
| {"k": 6} | |||
| 4 | |||
| 6 | |||
| $..o | {"j": 1, | $['o'] | Input value is |
| "k": 2} | visited | ||
| $.o..[*, | 1 | $['o']['j'] | Non-deterministic |
| *] | 2 | $['o']['k'] | ordering |
| 2 | $['o']['k'] | ||
| 1 | $['o']['j'] | ||
| $.a..[0, | 5 | $['a'][0] | Multiple segments |
| 1] | 3 | $['a'][1] | |
| {"j": 4} | $['a'][2][0] | ||
| {"k": 6} | $['a'][2][1] |
Table 16: Descendant Segment Examples
Note: The ordering of the results for the $..[] and $.. examples above is not guaranteed, except that:
-
{"j": 1, "k": 2} must appear before 1 and 2,
-
[5, 3, [{"j": 4}, {"k": 6}]] must appear before 5, 3, and [{"j":
4}, {"k": 6}],
- 5 must appear before 3, which must appear before [{"j": 4}, {"k":
6}],
-
5 and 3 must appear before {"j": 4}, 4, {"k": 6}, and 6,
-
[{"j": 4}, {"k": 6}] must appear before {"j": 4} and {"k": 6},
-
{"j": 4} must appear before {"k": 6},
-
{"k": 6} must appear before 4, and
-
4 must appear before 6.
The example above with the query $.o..[*, *] shows that a selector may produce nodelists in distinct orders each time it appears in the descendant segment.
The example above with the query $.a..[0, 1] shows that the child segment [0, 1] is applied to each node in turn (rather than the nodes being visited once per selector, which is the case for some JSONPath implementations that do not conform to this specification).