使用方法
- 「JSON 文档」框默认放了一份示例:store.book 是四本书组成的数组,每本书有 title、price、tags;store.bicycle 是单车对象。粘贴你自己的 JSON 覆盖即可,按 Ctrl+Enter(Mac 上 Cmd+Enter)立刻执行;被清空时执行查询会自动把这段示例填回去。
- 「路径表达式」默认 $.store.book[*].title,必须以 $ 开头。光标停在表达式框里按回车同样执行一次查询,不用去点按钮。
- 「表格最多显示」默认 50,范围 1 到 200。命中条数超过它时只列前若干条,并在结果行的括号里写明超出上限、只列前多少条,避免几万条结果把页面拖住。
- 表达式框支持边写边算:每改一个字符就执行一次,所以先写 $.store.book 会命中 1 条(book 数组本身),补上 [*].title 变成 4 条,再加 .. 又能看出递归下降带来的差别,不用等全部写完才验证。
- 结果区第一行是「命中 N 条」加一句当前写法的提示,下面逐条给出完整路径和值:字符串带双引号,对象与数组给出压缩后的 JSON,路径可以直接搬进代码当取值依据。
- 结果下面是命中明细表(序号 / 路径 / 值),默认显示 6 行,点「加载更多」展开全部,点「导出 CSV」存成带字节序标记的表格文件。
- 「复制结果」复制整段结论,「复制对照表」复制正文那张 12 行语法对照表(TSV,可直接粘进表格软件)。JSON 框被清空后点「执行查询」会自动把默认示例文档填回来。
- 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 行),方括号一类统一归在 [] 里说明。
| 写法 | 含义 | 写法 | 含义 |
|---|---|---|---|
| $ | 根对象 | [::2] | 切片步长 |
| .name | 取子字段(限标识符字符) | ..name | 递归下降:任意深度找该字段名 |
| ['name'] | 取子字段(可含空格或特殊字符) | .. | 递归下降全部节点 |
| [0] | 数组下标,支持负数倒取 | [?(expr)] | 过滤器(按实现而异,非标准统一) |
| [*] | 通配:数组全部元素或对象全部值 | @ | 过滤器内的当前节点 |
| [start:end] | 切片,左闭右开,可省略 | [1,3] | 并集下标(部分实现支持) |
读这张表抓住两条:一是下标与切片都是 0 起算且左闭右开,与 XPath 的 1 起算位置下标不是一回事;二是后三行(过滤器、@、并集下标)本页不支持,写了会收到明确提示而不是静默返回空。
结果边界、舍入与适用说明
- JSON 框为空时提示请把 JSON 粘贴进来,执行时会自动填回默认示例文档,不会返回上一次的结果。
- JSON 解析失败时提示「不是合法 JSON」并附上解析器给出的位置信息,常见原因是尾逗号、单引号、注释与全角引号。
- 表达式为空或不以 $ 开头时分别提示「表达式不能为空」与「表达式必须以 $ 开头」,并给出正确写法示例。
- 方括号没有闭合时提示 [ 与 ] 没有配对;表达式里出现无法识别的字符时指出具体是哪个字符。
- 数组下标越界时提示数组长度与合法区间,例如长度 4 的数组合法下标是 -4 到 3,写 [4] 或 [-5] 都会给出这条提示。
- 写了过滤器 [?()] 时提示本页不支持该写法并说明原因,不静默返回 0 条。
- 命中 0 条时区分两种情况:用了 .. 会提醒字段名可能写错,用了数字下标会提醒数组下标是 0 起算。
- 命中条数超过「表格最多显示」时只列前若干条并在提示条写明被截断的条数,结果文本区仍给出完整条数统计。
- 页面不联网、不写本地存储,JSON 与表达式只用于本次计算,刷新即清空。
常见问题
$..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 不会上传,也不写入本地存储。
相关工具
- JSON 格式化工具:先把压缩过的 JSON 展开缩进,再来跑路径表达式更容易看清层级。
- JSON 校验工具:解析报错时用它定位尾逗号、单引号与全角标点。
- JSON 差异工具:对比两份响应的字段增减,配合路径取值定位改动位置。
- CSV 转 JSON 转换器:把表格数据转成数组后,用 [*] 与切片批量取值。
- JSON 美化打印:调整缩进与换行,便于把结果贴进文档或issue。