JSONPath 的基本语法元素有哪些?
JSONPath 是一套用于定位 JSON 结构片段的路径表达式语法,由 Stefan Goessner 在 goessner.net 上提出。它的设计目标与 XPath 类似:XPath 用来选取 XML 文档中的节点,JSONPath 用来选取 JSON 中的部分数据。根据 goessner.net 的说明,JSONPath 最初只包含九种语法元素,用它们就能组合出相当复杂的路径表达式。下面按“从根出发、逐层定位”的顺序说明这些元素的作用。
从根开始:$
路径表达式以 $ 开头,表示 JSON 结构的根。例如:
{
"store": {
"book": [
{ "title": "A", "price": 10 },
{ "title": "B", "price": 20 }
]
}
}
$.store 选取根下的 store 对象。
访问成员与数组:点号与方括号
.用于访问对象成员,如$.store.book。[]既可以按名字访问成员,也可以按索引访问数组元素,如$.store.book[0]取第一本书。- 两者可以混用,
$.store.book[2].title就是 goessner.net 给出的示例写法,对应 XPath 中的//book[3]/title(注意 JSONPath 索引从 0 开始,XPath 位置从 1 开始)。
通配与递归:* 和 ..
*是通配符,匹配当前层级下的任意成员或元素,如$.store.*。..是递归下降,用于跨层级查找,不关心中间隔了多少层。$..book会找出结构中任意深度的book;$..book[2].title则先递归找到book,再取第三项的书名。
数组切片与并集
- 切片写在方括号里,形如
[start:end:step],用于选取数组的一段,例如$.store.book[0:2]。 - 并集用逗号分隔多个名字或索引,如
$.store.book[0,1]或$['store','other'],一次选取多个目标。
过滤表达式:?()
过滤用于按条件筛选数组元素或对象成员,写在 ?() 中,例如 $..book[?(@.price < 15)] 选出价格低于 15 的书。这里的 @ 代表当前正在判断的节点。
脚本表达式:()
括号内可写脚本表达式做进一步计算或取值,具体能力取决于所用实现的语言环境。
语法元素速查
| 元素 | 含义 |
|---|---|
$ |
根节点 |
. 或 [] |
访问成员 / 数组元素 |
* |
通配,匹配任意成员或元素 |
.. |
递归下降,跨层级查找 |
[start:end:step] |
数组切片 |
[a,b] |
并集,选取多个目标 |
?() |
过滤表达式 |
() |
脚本表达式 |
@ |
过滤或脚本中的当前节点 |
实现与获取方式
goessner.net 提供了 JSONPath 的轻量实现:jsonpath.js 用于客户端,jsonpath.php 用于服务端,页面说明可以免费下载。同一页面还提到 Atif Aziz 贡献了 C# 移植版 jsonpath.cs。不同语言、不同库对上述元素的覆盖范围可能不完全一致,实际使用时以所用实现的文档为准。
使用时的常见注意点
- 索引从 0 开始,与 XPath 的 1 起始位置不同,迁移表达式时要换算。
..递归下降在深层或大型结构上可能返回大量结果,也会带来性能开销,能确定层级时优先用具体路径。- 过滤表达式中的比较运算符和函数支持因实现而异,跨库移植前先验证。
- 路径表达式本身只负责“选取”,返回结果的形态(单个值、数组还是空)由实现决定,取值前应确认。