1. Introduction (引言)
1. Introduction (引言)
JSON [RFC8259] 是一种广泛使用的结构化数据值的表示格式. JSONPath 定义了一种字符串语法, 用于从给定 JSON 值中选择并提取其中的值.
相对于 JSON Pointer [RFC6901], JSONPath 无意取而代之, 而是作为能力更强的配套规范. 见附录 C.
1.1 Terminology (术语)
本文档中的关键词 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", "OPTIONAL" 必须按 BCP 14 [RFC2119] [RFC8174] 中所述的方式解释, 且仅当它们以全大写形式出现时适用.
本文档中的语法规则必须按 ABNF 解释, 如 [RFC5234] 所述. 本文档中 ABNF 的终结符值定义的是 Unicode scalar values (Unicode 标量值), 而非其 UTF-8 编码. 例如, Unicode 字符 PLACE OF INTEREST SIGN (U+2318) 在 ABNF 中应定义为 %x2318.
函数使用函数名后跟一对圆括号的方式引用, 如 fname().
除下文澄清之处外, 适用 [RFC8259] 的术语. 术语 "primitive (原始类型)" 与 "structured (结构化)" 用于按 [RFC8259] 第 1 节的方式对不同类型的值分组. JSON object (对象) 与 array (数组) 属于 structured; 其余值均为 primitive. "object", "array", "number", "string" 的定义保持不变. 重要的是, "object" 与 "array" 并不承担通用编程语境下的泛化含义.
适用 [RFC9485] 的术语.
本文档额外使用的术语定义如下.
Value (值): 按 [RFC8259], 指符合 JSON 通用数据模型的数据项, 即 primitive 数据 (数字, 文本字符串, 以及特殊值 null, true, false), 或 structured 数据 (JSON 对象与数组). [RFC8259] 侧重于 JSON 值的文本表示, 并未完整定义此处假定的值抽象.
Member (成员): 对象中的 name/value pair (名/值对). (成员本身不是值.)
Name (名称): 构成成员的 name/value pair 中的 name (字符串). [RFC8259] 也使用该词, 但该规范未正式定义; 此处为完整起见予以收录.
Element (元素): JSON 数组中的一个值.
Index (索引): 标识数组中某个特定元素的整数.
Query (查询): JSONPath expression (JSONPath 表达式) 的简称.
Query Argument (查询实参): JSONPath 表达式所作用于的值的简称.
Location (位置): 值在 query argument 内的位置. 可视为一串 name 与 index, 经由 query argument 中的对象与数组导航到该值; 空序列表示 query argument 自身. Location 可表示为 Normalized Path (规范化路径, 见下文定义).
Node (节点): 值与其在 query argument 内 location 组成的对.
Root Node (根节点): 其值为整个 query argument 的唯一节点.
Root Node Identifier (根节点标识符): 表达式 $, 指向 query argument 的根节点.
Current Node Identifier (当前节点标识符): 表达式 @, 在 filter expression (过滤器表达式, 后述) 求值语境中指当前节点.
Children (子节点) (某节点的): 若节点为数组, 则为其各 element 的节点; 若节点为对象, 则为其各 member value (成员值) 的节点. 若节点既不是数组也不是对象, 则没有子节点.
Descendants (后代节点) (某节点的): 该节点的子节点, 连同其子节点的子节点, 依此类推递归地包含. 更形式化地, 节点间的 "descendants" 关系是 "children" 关系的传递闭包.
Depth (深度) (后代节点在某值内): 该节点在该值内的祖先数量. 值的根节点深度为零, 根节点的子节点深度为一, 其子节点深度为二, 依此类推.
Nodelist (节点列表): 节点的列表. 虽然 nodelist 可以用 JSON 表示 (例如作为数组), 本文档不要求也不假定任何特定表示.
Parameter (形参): 函数的形式参数 (formal parameter), 可在 function expression (函数表达式) 中以 function argument (函数实参, 实际参数) 传入.
Normalized Path (规范化路径): 一种 JSONPath 表达式形式, 通过给出恰好产生该节点的查询来标识值中的节点. query argument 中的每个节点恰好由一个 Normalized Path 标识 (称该 Normalized Path 对该节点是 "unique (唯一)" 的), 且作为某 query argument 的 Normalized Path, 必须恰好标识一个节点. 这与 JSON Pointer [RFC6901] 类似, 但语法不同. 注意: 该定义基于第 2.7 节的语法定义; 能标识值中节点但不满足该语法的 JSONPath 表达式不是 Normalized Path.
Unicode Scalar Value: 任意 Unicode [UNICODE] 码点, 但排除 high-surrogate 与 low-surrogate 码点 (换言之, 为十六进制下 0 到 D7FF 或 E000 到 10FFFF 闭区间内的整数). JSONPath 查询是 Unicode scalar values 的序列.
Segment (片段): 从输入值中选择子节点 ([<selectors>]) 或后代节点 (..[<selectors>]) 的构造之一.
Selector (选择器): segment 内的单个条目, 接收输入值并产生由输入值的子节点组成的 nodelist.
Singular Query (奇异查询): 由 segment 构成的 JSONPath 表达式, 这些 segment 在语法上受到某种限制 (第 2.3.5.1 节), 使得无论输入值如何, 表达式产生的 nodelist 至多包含一个节点. 注意: 始终产生奇异 nodelist 但不满足第 2.3.5.1 节语法的 JSONPath 表达式不是 singular query.
1.1.1 JSON Values as Trees of Nodes (作为节点树的 JSON 值)
本文档将 query argument 建模为 JSON 值的树, 每个值对应自有节点. 节点要么是根节点, 要么是其后代.
本文档将查询作用于 query argument 的结果建模为 nodelist (节点列表).
节点是 query argument 中可被选择的部分. 查询仅能选择对象的 member values; 不能选择 member names 或 members (名/值对). 因此 member values 有节点, 而 members 与 member names 没有. 类似地, member values 是对象的子节点, 但 members 与 member names 不是.
1.2 History (历史)
本文档基于 Stefan Gössner 广受欢迎的 JSONPath 提案 (日期 2007-02-21) [JSONPath-orig], 汲取其广泛部署实现的经验, 并为其提供规范性说明.
附录 B 说明 JSONPath 如何受 XML 的 XPath [XPath] 启发.
JSONPath 旨在成为 PHP, JavaScript 等编程语言中 JSON 实现的轻量配套, 因此不像 XPath 那样定义自有表达式语言, 而是将查询的一部分委托给底层运行时, 例如 JavaScript 的 eval() 函数. 随着 JSONPath 在更多环境中实现, 表达式可移植性下降. 例如, 正则表达式处理常委托给便于使用的正则引擎.
本文档旨在去除此类实现相关依赖, 成为可在多种编程语言与环境间共用的 JSONPath 规范. 这意味着并非总能保持向后兼容; 本文档的设计原则是在实现之间采取 "共识", 即便略显粗糙, 只要不危及获得可用的稳定 JSON 查询语言这一目标.
术语 JSONPath 的选取既因 XPath 的启发, 也因查询结果由标识 JSON query argument 中节点的 paths (路径) 组成.
1.3 JSON Values (JSON 值)
按定义, JSONPath 查询所作用的 JSON 值必须是合法 JSON 值. JSON 值常通过解析 JSON text 构造.
将 JSON text 解析为 JSON 值的过程, 以及 JSON text 不表示合法 JSON 时的行为, 不由本文档定义. [RFC8259] 第 4 节与第 8 节指出了若干虽符合 JSON text 文法但并非 JSON 可互操作用法的情形, 可能导致不可预测行为. 本文档不试图为 JSONPath 查询在这些情形下定义可预测行为.
具体而言, 当所考虑对象之一的 JSON 值由存在多个同名 member ("duplicate names (重复名称)"; 见 [RFC8259] 第 4 节) 的 JSON text 构造时, 第 2.3.1, 2.3.2, 2.3.5, 2.5.2 节中 "Semantics (语义)" 小节描述的行为会变得不可预测. 此外, 按名称选择子节点 (第 2.3.1 节) 与比较字符串 (第 2.3.5.2.2 节) 时, 假定这些字符串为 Unicode scalar values 序列; 若非如此则行为不可预测 ([RFC8259] 第 8.2 节).
1.4 Overview of JSONPath Expressions (JSONPath 表达式概览)
JSONPath 表达式作用于称为 query argument 的 JSON 值. 输出为 nodelist.
JSONPath 表达式由一个 identifier (标识符) 后接零个或多个 segment 组成, 每个 segment 包含一个或多个 selector.
1.4.1. Identifiers (标识符)
根节点标识符 $ 指向 query argument 的根节点, 即整体实参.
当前节点标识符 @ 在 filter expression (第 2.3.5 节) 求值语境中指当前节点.
1.4.2. Segments (片段)
Segment 选择输入值的子节点 ([<selectors>]) 或后代节点 (..[<selectors>]).
Segment 可使用 bracket notation (方括号记法), 例如:
$['store']['book'][0]['title']
或更紧凑的 dot notation (点记法), 例如:
$.store.book[0].title
方括号记法包含一个或多个 (逗号分隔的) 任意种类 selector. Selector 详见下一节.
JSONPath 表达式可以混用方括号与点记法.
本文档将方括号记法视为 canonical (规范形式), 并相对于方括号记法定义点记法简写. 示例与描述在方便时使用简写.
1.4.3. Selectors (选择器)
Name selector (名称选择器), 例如 'name', 选择对象的具名子节点.
Index selector (索引选择器), 例如 3, 选择数组的带索引子节点.
在表达式 [] 中, wildcard (通配符) * (第 2.3.2 节) 选择节点的所有子节点; 在表达式 ..[] 中, 选择节点的所有后代节点.
Array slice (数组切片) start:end:step (第 2.3.4 节) 从数组中选择一系列元素, 给出起始位置, 结束位置, 以及从起始移动到结束的可选 step 值.
Filter expression (过滤器表达式) ?<logical-expr> 选择对象或数组的若干子节点, 例如:
$.store.book[[email protected] < 10].title
1.4.4. Summary (摘要)
表 1 简要概述 JSONPath 语法.
| Syntax Element (语法元素) | Description (描述) |
|---|---|
| $ | root node identifier (根节点标识符) (第 2.2 节) |
| @ | current node identifier (当前节点标识符) (第 2.3.5 节) |
| (仅在 filter selector 内有效) | |
[<selectors>] | child segment (子片段) (第 2.5.1 节): 选择 |
| 节点的零个或多个子节点 | |
| .name | ['name'] 的简写 |
| .* | [*] 的简写 |
..[<selectors>] | descendant segment (后代片段) (第 2.5.2 节): |
| 选择节点的零个或多个后代节点 | |
| ..name | ..['name'] 的简写 |
| ..* | ..[*] 的简写 |
| 'name' | name selector (名称选择器) (第 2.3.1 节): 选择 |
| 对象的具名子节点 | |
| * | wildcard selector (通配符选择器) (第 2.3.2 节): 选择 |
| 节点的所有子节点 | |
| 3 | index selector (索引选择器) (第 2.3.3 节): 选择 |
| 数组的带索引子节点 (从 0 起) | |
| 0💯5 | array slice selector (数组切片选择器) (第 2.3.4 节): |
| 数组的 start:end:step | |
?<logical-expr> | filter selector (过滤器选择器) (第 2.3.5 节): 使用 |
| logical expression (逻辑表达式) 选择特定子节点 | |
| length(@.foo) | function extension (函数扩展) (第 2.4 节): 在 |
| filter expression 中调用函数 |
表 1: JSONPath 语法概览
1.5 JSONPath Examples (JSONPath 示例)
本节为 informative (资料性). 提供 JSONPath 表达式示例.
示例基于图 1 所示的简单 JSON 值, 表示一家书店 (还包含一辆自行车).
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 399
}
}
}
图 1: 示例 JSON 值
表 2 展示若干可作用于该示例的 JSONPath 查询及其预期结果.
| JSONPath | Intended Result (预期结果) |
|---|---|
| $.store.book[*].author | 书店中所有图书的作者 |
| $..author | 所有作者 |
| $.store.* | 书店中所有条目, 即若干图书与一辆红色自行车 |
| $.store..price | 书店中一切的价格 |
| $..book[2] | 第三本书 |
| $..book[2].author | 第三本书的作者 |
| $..book[2].publisher | 空结果: 第三本书没有 "publisher" 成员 |
| $..book[-1] | 按顺序的最后一本书 |
| $..book[0,1] | 前两本书 |
| $..book[:2] | |
| $..book[[email protected]] | 所有带 ISBN 的书 |
| $..book[[email protected]<10] | 所有价格低于 10 的书 |
| $..* | 输入值中包含的所有成员值与数组元素 |
表 2: 应用于示例 JSON 值时的示例 JSONPath 表达式及其预期结果