JSON 工具箱

JSONPath 和 JSON Pointer 该怎么选

结论:JSON Pointer 是「唯一路径」,写法固定、能直接当 key 用;JSONPath 是「查询语言」,支持通配、递归、过滤。选错的典型症状是拿 JSONPath 去做配置读写,或者拿 Pointer 去做批量筛选。

进阶约 4 分钟发布于 2026-10-30更新于 2026-10-30
JSONPath 与 JSON Pointer 的能力边界

结论:要读写或存储某一个节点的地址就用 JSON Pointer(如 /server/cors/0),要按条件筛出一批节点就用 JSONPath;需要持久化的路径永远存 Pointer,不存表达式。

看你要的是「一个点」还是「一批点」。

一句话区分

JSON Pointer JSONPath
本质 唯一路径标识 查询表达式
语法 /a/b/0 $.a.b[0]、$..price
结果 恰好一个节点(或不存在) 零到多个节点
能当键存 ✅ 字符串即身份 ❌ 表达式,可能匹配多个
标准 RFC 6901 RFC 9535(2024 年才正式发布)

JSON Pointer 长什么样

以斜杠开头,每一段是一个层级,数组用下标:

/server/host            → "127.0.0.1"
/server/cors/0          → "https://a.com"
/                     → 整个文档

键名里如果本身含 / 或 ~,需要转义:~0 表示 ~,~1 表示 /。比如键名 a/b 写成 /a~1b。

它的价值在于确定性和可序列化:路径本身就是字符串,可以存进数据库、写进日志、作为配置项的 key,两端算出来的结果必然一致。JSON Patch(RFC 6902)就是靠它定位要改哪个节点。

JSONPath 长什么样

以 $ 开头表示根,支持通配与过滤:

$.store.book[*].author            → 所有作者
$..price                          → 递归找所有 price
$.store.book[?(@.price < 10)]     → 价格低于 10 的书
$..book[-1:]                      → 最后一本书

它更像 SQL 的 WHERE,返回的是一个集合。同一个表达式在不同数据上可能匹配 0 个、1 个或 100 个节点。

选错的两种典型症状

症状一:拿 JSONPath 当配置项 key。 配置系统里存 $.server.port,某天结构变成数组,这个表达式可能匹配到多个端口,改值逻辑就不知道改哪个。这种场景必须用 Pointer。

症状二:拿 Pointer 做筛选。 想找「所有 price 小于 10 的节点」,Pointer 做不到——它只能按固定路径走,不知道哪些节点存在。硬写循环遍历,等于自己实现一个残缺的 JSONPath。

实际项目里的分工

大多数成熟实现是两者并存:

  • 读配置、改字段、做 Patch:用 Pointer,路径固定,可审计
  • 数据探索、批量提取、报表取数:用 JSONPath,表达力优先
  • 需要存储的路径:一律用 Pointer,别存表达式

JSON Patch 与 Merge Patch 也是同理:Patch 用 Pointer 列表逐条操作,Merge Patch 用整体结构覆盖,前者精确、后者省事但不表达「删除数组元素」。

常见问题

JSON Pointer 和 JSONPath 应该怎么选?

看你要的是「一个点」还是「一批点」。要精确读写某个节点、并且希望这个路径能当键存起来,用 JSON Pointer,写法唯一,例如 /server/cors/0。要按条件捞出一批节点,用 JSONPath,例如 $.store.book[?(@.price < 10)]。

为什么不能把 JSONPath 表达式当配置项的 key?

因为表达式可能匹配多个节点。配置系统里存 $.server.port,某天结构变成数组,这个表达式就会匹配到多个端口,改值逻辑无法判断该改哪一个。需要持久化、可审计的定位必须用 Pointer。

能否用 JSON Pointer 做条件筛选?

不能。Pointer 只能按固定路径走,不知道哪些节点存在,所以「找出所有 price 小于 10 的节点」这类筛选它做不到。硬写循环遍历,等于自己实现一个残缺的 JSONPath。

相关工具

延伸阅读