JSONPath 查询工具

把 JSON 文档和一条路径表达式填进去,立刻得到所有命中的完整路径与值:支持 .name、['name']、[0]、[-1]、[*]、[start:end]、[::step] 和 ..name 递归下降,结果全部在本地算,JSON 不会上传。

使用方法

  1. 「JSON 文档」框默认放了一份示例:store.book 是四本书组成的数组,每本书有 title、price、tags;store.bicycle 是单车对象。粘贴你自己的 JSON 覆盖即可,按 Ctrl+Enter(Mac 上 Cmd+Enter)立刻执行;被清空时执行查询会自动把这段示例填回去。
  2. 「路径表达式」默认 $.store.book[*].title,必须以 $ 开头。光标停在表达式框里按回车同样执行一次查询,不用去点按钮。
  3. 「表格最多显示」默认 50,范围 1 到 200。命中条数超过它时只列前若干条,并在结果行的括号里写明超出上限、只列前多少条,避免几万条结果把页面拖住。
  4. 表达式框支持边写边算:每改一个字符就执行一次,所以先写 $.store.book 会命中 1 条(book 数组本身),补上 [*].title 变成 4 条,再加 .. 又能看出递归下降带来的差别,不用等全部写完才验证。
  5. 结果区第一行是「命中 N 条」加一句当前写法的提示,下面逐条给出完整路径和值:字符串带双引号,对象与数组给出压缩后的 JSON,路径可以直接搬进代码当取值依据。
  6. 结果下面是命中明细表(序号 / 路径 / 值),默认显示 6 行,点「加载更多」展开全部,点「导出 CSV」存成带字节序标记的表格文件。
  7. 「复制结果」复制整段结论,「复制对照表」复制正文那张 12 行语法对照表(TSV,可直接粘进表格软件)。JSON 框被清空后点「执行查询」会自动把默认示例文档填回来。
  8. JSON 解析失败、表达式不以 $ 开头、方括号没闭合、下标越界、写了过滤器 [?()] 等,都会给出对应情况的具体提示,不会拿上一次的结果冒充本次输出。

这个 JSONPath 查询工具能解决什么问题

第一类问题是接口返回一大坨 JSON,只想确认里面某几个字段的值。把响应体粘进来,写 $.data.list[0].status 之类的路径就能直接看到值,不必临时写循环、也不必在代码里打日志再回头翻控制台;调试线上问题时,这条路往往比重新发一次请求更快。

第二类问题是数组取值与切片。四本书里要第 2、3 本的价格,写 $.store.book[1:3].price 命中 2 条(12.99 与 8.99),左闭右开;要偶数位写 [::2],命中第 0 与第 2 本;要最后一本写 [-1]。这些写法与 Python 的切片语义一致,不用再手写 filter 加 map。

第三类问题是深层嵌套里找不到字段在哪一层。..name 递归下降会遍历所有层级并收集同名 key,$..price 在本页示例里命中 5 条而不是 4 条,因为 bicycle.price(19.95)也会被捞出来。这个「多出来的一条」正是递归下降最容易误用的地方,本页把它显式标注出来。

第四类问题是核对别人的数字。同一条表达式在不同库里结果可能不一样,因为 JSONPath 长期没有正式标准。把表达式和 JSON 一起放进本页跑一遍,能确认命中条数与路径写法,再拿去和你的生产代码对账,比口头争论有效。

这个工具在本站也叫「JSONPath查询」,路径表达式里的 $ 代表根对象,下面会讲清每个操作符的边界语义。

计算原理与变量说明

求值分三步:先把表达式切成 token,再按 token 顺序在节点集合上逐步推进,最后把剩下的节点展开成「路径 + 值」的清单。每一步的输入都是一组 {路径, 值} 对,输出也是一组,所以通配符与递归下降天然能一次命中多条。

第一步,分词。表达式必须以 $ 开头,否则直接报错。$ 之后逐个读字符:遇到 . 且后面还是 . 记一个递归 token;遇到单个 . 就读到第一个非标识符字符为止,记一个字段名 token;遇到 [ 就按括号深度一直读到配对的 ],把括号内部整体记成一个 token(所以 ['name'] 里的空格与标点不会被切坏);遇到裸的标识符也记成字段名。

第二步,逐个 token 推进。字段名 token 在每个节点上取同名子字段,节点不是对象或字段不存在就丢弃;方括号 token 按括号内的写法分四类处理。

方括号的四类写法。[*] 是通配:数组取全部元素并在路径上补 [下标],对象取全部值并在路径上补 ['键名'];[n] 是下标,支持负数,[-1] 表示最后一个,越界则这条不命中;[start:end] 与 [start:end:step] 是切片,左闭右开,省略端按步长方向补全,负数从末尾算;['name'] 是字符串键,用来取带空格或特殊字符的字段名。

递归下降用广度优先。..name 从当前节点集合出发,用队列逐层展开,同时用一个已访问集合防止循环引用把页面卡死。它是按文档顺序、按层级由浅到深收集同名 key 的,所以 $..price 会先给出 $.store.bicycle.price(19.95)再给出四本书的 price,顺序稳定可复现。

为什么不支持过滤器。[?(@.price < 10)] 这类写法在 Goessner 原文里只有一句示例,各家实现各取所需:比较符、正则、脚本表达式互不相同。既然做不到一致,本页选择明确不支持并给出提示,而不是让你以为「写了没生效」。

标准现状。JSONPath 由 Goessner 在 2007 年提出,长期是事实标准,直到 2024 年才由 RFC 9535 定出正式规范。规范出台前的存量实现不会自动对齐,所以跨库迁移时一定要用同一份数据实测命中条数,不能只信文档里的说法。

完整示例(数值仅作演示)

基准文档是 {"store":{"book":[4 本],"bicycle":{"color":"red","price":19.95}}},四本书依次是 Sayings(8.95)、Sword(12.99)、Moby(8.99)、King(22.99),tags 分别是 [a,b]、[c]、[]、[d,e]。

$.store.book[*].title 命中 4 条:$.store.book[0].title = "Sayings"、[1] = "Sword"、[2] = "Moby"、[3] = "King"。改成 $.store.book[0].title 就只剩 1 条 Sayings,改成 [-1] 取 price 得到 22.99,也就是最后一本 King 的价格。

切片:$.store.book[0:2].title 命中 2 条(Sayings、Sword),左闭右开所以不含下标 2;$.store.book[::2].title 命中 2 条(Sayings、Moby),步长 2 取偶数位;$.store.book[1:3].price 命中 2 条,分别是 12.99 与 8.99。

递归下降:$..price 命中 5 条,依次是 $.store.bicycle.price = 19.95、$.store.book[0].price = 8.95、[1] = 12.99、[2] = 8.99、[3] = 22.99;$..title 命中 4 条,因为文档里只有四本书有 title。这里 5 与 4 的差就是 bicycle 那一条。

字符串键与嵌套通配:$.store.bicycle['color'] 命中 1 条 "red",方括号里写引号键名与写 .color 等价;$.store.book[*].tags[*] 命中 5 条,分别是 book[0].tags[0] = "a"、[0].tags[1] = "b"、[1].tags[0] = "c"、[3].tags[0] = "d"、[3].tags[1] = "e",Moby 的 tags 是空数组所以不产生命中。

把 JSON 换成你自己的文档时,先用 $ 单独跑一遍确认能解析,再逐段往下加:先 .字段名,再加 [*],最后加 ..name。每加一段看一眼命中条数,比一口气写完再排查省事。

JSONPath 语法对照表

下表 12 行是本页支持的完整语法(前 9 行)与明确不支持或需注意的写法(后 3 行),方括号一类统一归在 [] 里说明。

读这张表抓住两条:一是下标与切片都是 0 起算且左闭右开,与 XPath 的 1 起算位置下标不是一回事;二是后三行(过滤器、@、并集下标)本页不支持,写了会收到明确提示而不是静默返回空。

结果边界、舍入与适用说明

常见问题

$..price 为什么命中 5 条而不是 4 条?

因为 ..(递归下降)会遍历所有层级收集同名 key。示例文档里 bicycle 也有 price(19.95),它和四本书的 price 一起被捞出来,所以是 5 条。只想取书的价格就写成 $.store.book[*].price,不要用 ..。

[-1] 取的是哪个元素?下标是从 0 还是从 1 开始?

下标从 0 起算,[-1] 表示最后一个元素,[-2] 表示倒数第二个。示例里 $.store.book[-1].price 取到 22.99,也就是第四本 King。这与 Python 的负索引语义一致,与 XPath 的 1 起算位置下标不同。

切片 [1:3] 到底含不含第 3 个元素?

不含。切片是左闭右开:[1:3] 取下标 1 与 2,两个元素。示例 $.store.book[1:3].price 命中 2 条,12.99 与 8.99。要含到最后就省略右端写成 [1:],右端缺省按数组长度补全。

[?(@.price < 10)] 为什么提示不支持?

过滤器在 Goessner 原文里只有一句示例,比较符、正则、脚本表达式在各家实现里互不相同,做不到一致。本页选择明确报错而不是给出可能与你的生产库不一致的结果,请改用下标、切片或先把数据筛好再粘进来。

字段名里有空格或点号,用 .name 取不到怎么办?

改用方括号加引号的写法 ['name']。分词时方括号内部是按括号深度整体取出的,所以空格、点号、连字符都不会被切坏;.name 只能读由字母、数字、下划线与 $ 组成的标识符。

提示下标越界,可我明明数的是第 4 个元素?

数组下标从 0 起算,第 4 个元素的下标是 3。长度 4 的数组合法下标是 0、1、2、3,负数写法是 -4 到 -1;写 [4] 就越界了,本页会给出数组长度与合法区间。

这个工具免费吗?

免费,无需注册即可使用。

输入的数据安全吗?

安全。解析与求值都在当前浏览器本地完成,JSON 不会上传,也不写入本地存储。

相关工具