2.5. Segments (片段)
2.5. Segments (片段)
对输入 nodelist 中的每个节点, segment 对该节点应用一个或多个 selector, 将每个 selector 的结果拼接为按输入节点分的 per-input-node nodelist, 再按输入 nodelist 顺序拼接为单一 segment 结果 nodelist.
查询中 segment 越多, 结果 nodelist 中节点在输入值中的深度越大:
-
含 N 个 segment 的查询, N >= 0, 产生深度在输入值中至少为 N 的节点的 nodelist.
-
含 N 个 segment 的查询, N >= 0, 且全部为 child segment (第 2.5.1 节), 产生深度在输入值中恰好为 N 的节点的 nodelist.
Segment 有两种: child segment 与 descendant segment.
segment = child-segment / descendant-segment
各类 segment 的语法与语义见下文.
2.5.1. Child Segment (子片段)
2.5.1.1. Syntax (语法)
Child segment 由方括号括起的非空逗号分隔 selector 序列组成.
单个 wildcard 或 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
., 直接由 wildcard-selector 构成的 child-segment, 是 [] 的简写.
.
2.5.1.2. Semantics (语义)
Child segment 包含 selector 序列, 每个 selector 选择输入值的零个或多个子节点.
不同种类的 selector 可出现在同一 child segment 内.
对输入 nodelist 中的每个节点, child segment 的结果 nodelist 为其各 selector 的 nodelist 按列表中出现顺序的拼接. 注意: 被多个 selector 匹配的节点在 nodelist 中保留相应次数.
Selector 可产生多种可能顺序时, child segment 中该 selector 的每次出现都可能产生不同顺序的 nodelist.
总之, child segment 向输入值的结构再深入一层.
2.5.1.3. Examples (示例)
JSON:
["a", "b", "c", "d", "e", "f", "g"]
Queries:
| Query | Result | Result | Comment |
|---|---|---|---|
| Paths | |||
| $[0, | "a" | $[0] | Index |
| 3] | "d" | $[3] | |
| $[0:2, | "a" | $[0] | Slice 与 |
| 5] | "b" | $[1] | index |
| "f" | $[5] | ||
| $[0, | "a" | $[0] | 重复 |
| 0] | "a" | $[0] | 项 |
表 15: Child Segment 示例
2.5.2. Descendant Segment (后代片段)
2.5.2.1. Syntax (语法)
Descendant segment 由双点 .. 后接 child segment (使用方括号记法) 组成.
也提供与 child segment 简写形式对应的简写.
descendant-segment = ".." (bracketed-selection /
wildcard-selector /
member-name-shorthand)
.., 直接由 wildcard-selector 构成的 descendant-segment, 是 ..[] 的简写.
..
注意: 单独的 .. 不是合法 segment.
2.5.2.2. Semantics (语义)
Descendant segment 产生输入值的零个或多个后代节点.
对输入 nodelist 中的每个节点, descendant selector 访问输入节点及其每个后代, 满足:
-
任意 array 的节点按 array 顺序访问, 且
-
节点在其后代之前访问.
Object 子节点的访问顺序不予规定, 因为 JSON object 无序.
设 descendant segment 形如 ..[<selectors>] (将任意简写转为方括号记法后), 按访问顺序的节点为 D1, ..., Dn (n >= 1). 注意: D1 为输入值.
对每个满足 1 <= i <= n 的 i, 将 nodelist Ri 定义为对节点 Di 应用 child segment [<selectors>] 的结果.
对输入 nodelist 中的每个节点, descendant segment 的结果为 R1, ..., Rn 按该顺序的拼接. 再按输入 nodelist 顺序拼接这些结果, 形成 segment 的结果.
总之, descendant segment 向每个输入值的结构深入一层或多层.
2.5.2.3. Examples (示例)
JSON:
{
"o": {"j": 1, "k": 2},
"a": [5, 3, [{"j": 4}, {"k": 6}]]
}
Queries:
(注意第四个示例可用两个等价查询表达, 表 16 中合并为一行而非两行几乎相同的行.)
| Query | Result | Result Paths | Comment |
|---|---|---|---|
| $..j | 1 | $['o']['j'] | Object |
| 4 | $['a'][2][0]['j'] | 值 | |
| $..j | 4 | $['a'][2][0]['j'] | 另一种 |
| 1 | $['o']['j'] | 结果 | |
| $..[0] | 5 | $['a'][0] | Array |
| {"j": 4} | $['a'][2][0] | 值 | |
| $..[*] | {"j": 1, | $['o'] | 所有值 |
| 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'] | 访问了 |
| "k": 2} | 输入值 | ||
| $.o..[*, | 1 | $['o']['j'] | 非确定 |
| *] | 2 | $['o']['k'] | 顺序 |
| 2 | $['o']['k'] | ||
| 1 | $['o']['j'] | ||
| $.a..[0, | 5 | $['a'][0] | 多个 |
| 1] | 3 | $['a'][1] | segment |
| {"j": 4} | $['a'][2][0] | ||
| {"k": 6} | $['a'][2][1] |
表 16: Descendant Segment 示例
注意: 上文 $..[] 与 $.. 示例的结果顺序不予保证, 但:
-
{"j": 1, "k": 2} 必须出现在 1 与 2 之前,
-
[5, 3, [{"j": 4}, {"k": 6}]] 必须出现在 5, 3 与 [{"j": 4}, {"k": 6}] 之前,
-
5 必须出现在 3 之前, 3 必须出现在 [{"j": 4}, {"k": 6}] 之前,
-
5 与 3 必须出现在 {"j": 4}, 4, {"k": 6} 与 6 之前,
-
[{"j": 4}, {"k": 6}] 必须出现在 {"j": 4} 与 {"k": 6} 之前,
-
{"j": 4} 必须出现在 {"k": 6} 之前,
-
{"k": 6} 必须出现在 4 之前, 且
-
4 必须出现在 6 之前.
查询 $.o..[*, *] 的示例表明, selector 在 descendant segment 中每次出现都可能产生不同顺序的 nodelist.
查询 $.a..[0, 1] 的示例表明, child segment [0, 1] 依次应用于每个节点 (而非某些不符合本规范的 JSONPath 实现那样每个 selector 只遍历节点一次).