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 起始位置不同,迁移表达式时要换算。
  • .. 递归下降在深层或大型结构上可能返回大量结果,也会带来性能开销,能确定层级时优先用具体路径。
  • 过滤表达式中的比较运算符和函数支持因实现而异,跨库移植前先验证。
  • 路径表达式本身只负责“选取”,返回结果的形态(单个值、数组还是空)由实现决定,取值前应确认。
goessner.net