接口返回三百行,你只要其中三个字段

这种场景做过接口的都熟:调试一个订单查询,响应体压缩前有几百上千行,嵌套三四层,数组里套对象,对象里再套数组。你真正关心的可能只有订单号、状态和一个手机号。用眼睛在一堆大括号里扫,扫到第三个字段已经忘了第一个长什么样。

有人习惯把 JSON 复制到编辑器里按 Ctrl+F 搜键名。字段名唯一的时候还行,一旦遇到 id、name、status 这种在每一层都出现的高频键名,搜索结果能给你列出十几个候选,还得自己判断哪个是主订单的、哪个是商品明细的。

JSONPath 就是来解决这个问题的。它不给 JSON 加任何语法,只是约定一套描述「路径」的写法,让你能说清楚「我要的是 data 下面 list 数组里每一项的 orderNo」,而不是靠猜和搜。

JSONPath 的基本思路:把文件路径那套搬到数据结构上

如果用过命令行或者写过前端路由,理解 JSONPath 会很快,因为它和文件路径是同一类思路:从起点出发,一层一层往下走,每走一步就缩小范围。

区别在于文件的层级是目录和文件名,JSON 的层级是键和数组下标。JSONPath 用 $ 代表整份文档的根,也就是最外面那对大括号;用点号 . 或者方括号 [] 往下走一层。下面这份数据拿来举例,后面所有写法都基于它:

{
  "code": 0,
  "data": {
    "total": 2,
    "list": [
      { "orderNo": "A1001", "amount": 128, "buyer": { "nick": "小林" } },
      { "orderNo": "A1002", "amount": 899, "buyer": { "nick": "阿哲" } }
    ]
  }
}

要拿状态码,表达式是 $.code。要拿总数,是 $.data.total。这两个例子说明了一个容易忽略的点:路径里的每一段都必须真实存在,少写或多写一层都不会报错,只会得到空结果。这也是新手最常卡住的地方,后面单独说。

常用写法逐个说:属性、索引、通配符、递归、条件筛选

日常查询真正用到的表达式其实不多,下面这几个覆盖了绝大多数场景。

属性访问用点号连接键名,$.data.total 是最直白的形式。键名里带点号、减号或者空格时,用方括号加引号的写法更稳妥,比如 $['order-no']。写接口对接文档的时候,字段名带连字符的情况比想象中多。

数组索引用方括号里的数字,$.data.list[0] 取第一项。注意下标从 0 开始,这是几乎所有编程语言的约定,但从 Excel 或者业务文档转过来的人容易顺手写成 1。上面的数据里 $.data.list[1].orderNo 得到的是 A1002。

通配符用星号 *,意思是「这一层里的每一个」。$.data.list[*].orderNo 会把两个订单号一起取出来,$.data.* 则把 data 下面所有键对应的值都列出来。通配符的好处是不用知道具体有几个元素,代价是结果往往是一批,需要自己再挑。

递归查找用两个点 ..,它会从当前位置往下遍历整棵树,找出所有满足后面条件的节点。$..nick 不管 nick 藏在第几层,只要能到就会命中,上面例子里两个昵称都会返回。这个写法的适用场合是结构不固定:同一个接口,有的订单带了 buyer 有的没带,或者干脆嵌在别的层里。

条件筛选用方括号里加问号的写法,用来按字段值挑元素,比如只取金额大于 200 的那些项。这类表达式适合快速剔除明显的无关数据,但它属于轻量实现的范围,复杂嵌套条件和函数调用不一定支持,写之前最好拿小样例试一下。

写法含义示例与结果
$.data.total按层级取属性得到 2
$.data.list[0]取数组第一项整个第一笔订单对象
$.data.list[*].orderNo取每一项的某个字段两个订单号
$..nick递归找任意层级两个买家昵称
$..list[?(@.amount>200)]按条件筛选金额大于 200 的订单

表格里最后一行用到了 @,它表示「当前正在判断的这个元素」,可以理解成循环里的临时变量。条件里的比较符号可以直接写大于小于,大于号在 HTML 页面里需要写成实体,粘贴到工具里则用普通符号就行。

在线查询比写代码试更快

知道写法之后,真正费时间的是调试表达式。在项目里试,意味着改一次代码、跑一次程序、打一次日志,一轮下来几分钟。用在线工具就能把这个循环压到几秒钟。

打开 JSONPath 查询 工具后,左边贴 JSON,右边填表达式,结果区立刻显示匹配到的值和它的路径。这个「路径」显示很关键:表达式写错时,你不仅知道没匹配上,还能看出工具是按什么路径找的,从而定位自己是层级写错了还是键名拼错了。界面提供载入示例按钮,不想翻自己数据的时候可以直接点开样例边改边试。

  1. 把接口返回的 JSON 整段粘进 JSON 数据框,或者用格式化工具处理好缩进再粘。
  2. 在表达式框输入路径,从 $ 开始,一层一层往下写,不确定层级时先用 .. 加键名试。
  3. 看结果区的值和路径,确认取对了再用复制结果按钮拿走。
  4. 要批量取字段时,把表达式改成通配符形式,一次看全所有匹配项。

整个过程在浏览器里完成,JSON 不会上传到服务器。处理带内部字段、订单号、手机号的真实数据时,这一点比随手贴进某个在线输入框要踏实些。

容易踩的几个坑

键名区分大小写。$.Data.list 和 $.data.list 是两个结果。Java 写的接口返回大写开头字段的情况不少见,复制字段名比手打靠谱。

取到的可能是对象而不是值。表达式停在某一层时,返回的是那一整块内容。$.data.list[0] 拿到的是订单对象,想只要订单号得继续往下写 .orderNo。结果区如果显示出一大段大括号,就说明路径少写了一层。

递归查找的开销。数据小的时候 .. 很爽,几十万行的日志 JSON 用它就会明显卡顿,而且返回一堆你不需要的节点。明确知道层级时,写清楚路径永远更快。

数字和字符串不一样。"128" 和 128 在 JSON 里是两种类型,做条件比较时类型不一致可能筛不出结果。从接口拿到的数字被引号包起来是很常见的现象,看一眼引号就能避免。

数组越界不等于报错。$.data.list[5] 在只有两项的时候返回空,不会给提示。看到空结果先数一下数组长度。

和格式化、校验工具配合着用

JSONPath 经常不是单独使用的。数据压成一行看不清结构时,先用 JSON 格式化 展开缩进,把层级理清楚,再回来写路径,比对着压缩数据猜要快得多。如果是要确认这份响应结构是否符合约定,比如必填字段有没有缺、类型对不对,那是 JSON Schema 校验 的活,它按规则逐项检查并指出不符合的位置。

取到数据之后如果想交给 Excel 做透视或者给运营同事看,可以用 JSON 转 CSV 把数组转成表格,注意转换时的编码选项,避免中文变乱码。这一套串下来是:格式化看清结构、校验确认合规、JSONPath 挑出目标字段、转 CSV 交付。手边有这四件事的工具,处理接口数据就不用为了看一眼字段去开 IDE 了。

常见问题 FAQ

JSONPath 和 JSON 格式化有什么区别?

格式化解决的是「看不懂」,它把压缩成一行的 JSON 展开成有缩进的结构,方便人眼扫。JSONPath 解决的是「找不到」,它按路径把你要的那一小段取出来。实际工作里两个经常连着用:先用格式化工具看清整体结构,再用 JSONPath 把目标节点挑出来。

为什么我的表达式一个结果都没匹配到?

先检查三层。一是根节点写错了,路径必须从 $ 开始。二是层级不对,中间少写或多写了一层,比如把 data.list 写成 list。三是大小写,JSON 的键名是区分大小写的,Name 和 name 是两个东西。用递归写法 ..键名 先跑一遍,能匹配上说明是层级问题。

递归查询 .. 是不是用得越多越好?

不是。递归查找会遍历整棵树的每一个节点,数据量大时明显变慢,而且匹配到的结果往往一大片,还得自己筛。知道确切层级时优先写明确路径,只有在结构不固定、字段位置可能变化时才用递归。

在线 JSONPath 工具会把我粘贴的数据上传吗?

速工具的 JSONPath 查询是纯前端实现,表达式在浏览器里逐个节点解析,数据不离开本机,也不会执行任何代码。所以带内部字段、接口密钥那类样例数据,处理起来比随手贴进在线聊天窗口要稳妥。