JSONPath 实战:从嵌套 API 响应中提取数据的正确姿势

遇到的真实问题 ``json { "code": 200, "data": { "user": { "profile": { "name": "张三", "contacts": [ {"type": "email", "value": "zhangsan@example.

遇到的真实问题

{
  "code": 200,
  "data": {
    "user": {
      "profile": {
        "name": "张三",
        "contacts": [
          {"type": "email", "value": "[email protected]"},
          {"type": "phone", "value": "13800138000"}
        ]
      }
    },
    "orders": [
      {"id": 1, "amount": 99.99, "status": "paid"},
      {"id": 2, "amount": 199.99, "status": "pending"}
    ]
  }
}
我需要提取:
  • 用户姓名
  • 所有邮箱地址
  • 已支付的订单金额
用代码写多层循环和判断?不,直接用 JSONPath。

正确的 JSONPath 表达式

1. 提取用户姓名

$.data.user.profile.name
结果:"张三"

2. 提取所有邮箱地址

$.data.user.profile.contacts[?(@.type=='email')].value
结果:["[email protected]"]

3. 提取已支付订单的金额

$.data.orders[?(@.status=='paid')].amount
结果:[99.99]

4. 提取所有订单 ID 和金额

$.data.orders[*].[id,amount]
结果:[[1,99.99],[2,199.99]]

在工具迷上测试

打开 JSONPath Tester,把 API 响应粘贴到左侧,右侧输入表达式,点击"测试"。 工具会立即显示匹配结果,帮你验证表达式是否正确。

常见的 JSONPath 错误

错误 1:忘记 $ 符号

❌ data.user.name
✅ $.data.user.name

错误 2:数组索引从 1 开始

❌ $.data.orders[1]  // 这是第二个元素
✅ $.data.orders[0]  // 这才是第一个元素

错误 3:过滤器语法错误

❌ $.data.orders[?(@.status=paid)]    // 单个等号
❌ $.data.orders[?(@.status==paid)]   // 没有引号
✅ $.data.orders[?(@.status=='paid')] // 正确

错误 4:递归查找过度使用

❌ $..name  // 会找所有层级的 name,可能匹配太多
✅ $.data.user.profile.name  // 明确路径更精确

错误 5:引号使用错误

❌ $.data.orders[?(@.status=="paid")]  // 双引号在某些解析器中会出错
✅ $.data.orders[?(@.status=='paid')]  // 单引号更稳定

实战技巧

技巧 1:先测试父路径

不确定数据结构?先测试父路径:
$.data              // 确认能取到 data
$.data.user         // 确认能取到 user
$.data.user.profile // 确认能取到 profile

技巧 2:使用切片

只需要前 3 个订单?
$.data.orders[0:3]

技巧 3:取最后一个元素

$.data.orders[-1:]

技巧 4:多字段选择

同时获取多个字段:
$.data.orders[*].[id,status]

技巧 5:复杂条件过滤

金额大于 100 且状态为已支付:
$.data.orders[?(@.amount>100 && @.status=='paid')]

FAQ

  • Q: JSONPath 和 JSON 有什么区别?
A: JSON 是数据格式,JSONPath 是查询语言。就像 SQL 是数据库查询语言,JSONPath 是 JSON 查询语言。
  • Q: 所有 JSON 库都支持 JSONPath 吗?
A: 不是。Java 的 JsonPath 库、JavaScript 的 JSONPath-plus 库、Python 的 jsonpath-ng 库支持。使用前确认你的库支持。
  • Q: 为什么我的表达式在工具迷上可以,但在代码里不行?
A: 不同库的语法略有差异。工具迷使用标准 JSONPath 语法,建议在代码中使用相同的库(如 Java 的 com.jayway.jsonpath)。
  • Q: 可以修改 JSON 数据吗?
A: JSONPath 只能读取,不能修改。要修改需要先解析成对象,修改后再序列化。
  • Q: 性能如何?
A: 简单表达式很快。复杂递归查找(如 $..name)在大 JSON 上可能较慢。建议明确路径。
  • Q: 如何处理空值或缺失字段?
A: 使用 ?() 过滤器:
$.data.orders[?(@.amount)]
只返回有 amount 字段的订单。

完整示例

API 响应数据(简化版):
{
  "data": {
    "products": [
      {"id": 1, "name": "iPhone", "price": 999, "inStock": true},
      {"id": 2, "name": "MacBook", "price": 1999, "inStock": false},
      {"id": 3, "name": "iPad", "price": 799, "inStock": true}
    ]
  }
}
提取所有有库存的商品名称:
$.data.products[?(@.inStock==true)].name
结果:["iPhone","iPad"]
需要处理复杂的 JSON 数据?在 工具迷的 JSONPath Tester 上实时测试你的表达式。