跳到主要内容

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 节): 选择
节点的所有子节点
3index selector (索引选择器) (第 2.3.3 节): 选择
数组的带索引子节点 (从 0 起)
0💯5array 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 查询及其预期结果.

JSONPathIntended 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 表达式及其预期结果