接口返回一层层嵌套的 JSON,想定位某个字段还要写 data.result.items[0].profile.name?JSONPath 一行 $..name 就能找到。下面 10 个模式覆盖日常 90% 场景,每个都附 JS 表达式等价写法。
1. 根节点 $
$
整个 JSON 对象。输入空表达式也是这个效果,主要作为其他查询的起点。
2. 点路径 $.a.b
$.store.book
从根开始按字段名一层层向下。等价 JS 的 data.store.book。不支持字段名含特殊字符(如 $.data.a-b),此时用方括号语法:
$['data']['a-b']
3. 数组索引 $[n]
$.store.book[0]
数组第 n 个元素,从 0 开始。负数 $.book[-1] 取倒数第一个,等价 JS 的 arr.at(-1)。
4. 数组切片 $[start:end:step]
$.book[0:3] 前 3 个
$.book[-2:] 最后 2 个
$.book[::2] 每隔一个
语法和 Python 切片一致。比 Array.prototype.slice 多一个 step 参数。
5. 通配符 $.a[*]
$.store.book[*].title
数组所有元素的 title。等价 JS 的 .map(x => x.title)。对对象用 * 表示所有值:$.store.*。
6. 递归下降 $..key
$..price
整棵树上所有名为 price 的字段。不关心层级,一把抓。日志、配置里找某个字段最有用——不需要先搞清完整路径。
7. 过滤表达式 [?(...)]
$.store.book[?(@.price < 10)]
@ 代表当前元素。筛出 price 小于 10 的 book。常见写法:
$.user[?(@.age >= 18)] 成年用户
$.log[?(@.level == 'error')] 只看错误日志
$.item[?(@.tags)] 有 tags 字段的
8. 多条件过滤
$.book[?(@.price < 10 && @.stock > 0)]
&&、||、! 都可用。不要写多余的外层括号如 ((@.price<10) && (@.stock>0))——一些解析器会拒绝。
9. 正则过滤 =~
$.user[?(@.email =~ /.+@gmail\.com/)]
正则匹配字符串。斜杠两端是字面量形式。不是所有实现都支持——本工具的 jsonpath-plus 支持,Jayway 要开 INLINE_SIMPLE_OPERATIONS。
10. 索引并集 [0,2,4]
$.book[0,2,4].title
同时取 0、2、4 位的 title。少见但偶尔方便。多数场景用 filter 或 slice 更清晰。
JS 表达式:JSONPath 搞不定的兜底
所有 JSONPath 只读查询都能翻译成 JS,而且 JS 还能做变形:
| 需求 | JSONPath | JS 表达式 |
|---|---|---|
| 提取字段 | $..name | .data.flatMap(x => x.name) |
| 过滤 + 映射 | 做不到 | .items.filter(x => x.active).map(x => x.id) |
| 聚合求和 | 做不到 | .orders.reduce((s, x) => s + x.amount, 0) |
| 分组 | 做不到 | Object.groupBy(.users, x => x.role) |
| 去重 | 做不到 | [...new Set(.tags)] |
| 排序 | 做不到 | .list.toSorted((a,b) => b.score - a.score) |
选型原则:只读查询、定位字段用 JSONPath——简洁;过滤、聚合、变形用 JS 表达式——表达力强。本工具里两种语法都能直接执行:以 $ 开头走 JSONPath,以 . 或 [ 开头自动补 data 前缀走 JS。
踩坑清单
$可以省略:本工具里.a.b等价于$.a.b(点开头自动补前缀);如果写data.a.b会按 JS 表达式执行$..key可能很慢:深递归,百万行 JSON 上用一次没问题,循环里调每秒多次会卡- 字符串值要加引号:
$.book[?(@.name == 'Moby')],漏引号就变成变量引用了 - 数字/字符串比较要一致:
@.id == 5和@.id == '5'不等价(严格相等) - 空结果不一定是语法错:路径正确但没匹配到也返回
[],别以为是表达式错了——先在树视图里找下字段确实存在
掌握 JSONPath 定位 + JS 变形两把刀,90% 的 JSON 手术都能就地完成。