JSONPath в действии: правильный способ извлечения данных из вложенных ответов API

Возникли реальные проблемы ``json { "code": 200, "data": { "user": { "profile": { "name": "Zhang San", "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. Извлеките все идентификаторы заказов и суммы

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

Тест на Tools Obsession

Откройте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')]

Часто задаваемые вопросы

  • В: В чем разница между JSONPath и JSON?
О: JSON — это формат данных, а JSONPath — это язык запросов. Подобно тому, как SQL — это язык запросов к базе данных, JSONPath — это язык запросов JSON.
  • Вопрос: Все ли библиотеки JSON поддерживают JSONPath?
О: Нет. Поддерживается библиотекой JsonPath Java, библиотекой JSONPath-plus JavaScript и библиотекой jsonpath-ng Python. Прежде чем использовать его, убедитесь, что ваша библиотека его поддерживает.
  • В: Почему мое выражение работает в инструменте, но не в коде?
О: Синтаксис разных библиотек немного отличается. Любители инструментов используют стандартный синтаксис JSONPath и рекомендуют использовать в своем коде ту же библиотеку (например, com.jayway.jsonpath в Java).
  • В: Можно ли изменить данные JSON?
О: JSONPath можно только читать, но не изменять. Чтобы изменить его, его необходимо сначала проанализировать в объект, а затем сериализовать после модификации.
  • В: Как производительность?
О: Простые выражения выполняются быстро. Сложный рекурсивный поиск (например, $..name) может быть медленным для больших JSON. Рекомендуется уточнить путь.
  • В: Как быть с нулевыми значениями или отсутствующими полями?
A: Используйте ?() фильтр:
$.data.orders[?(@.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 для любителей инструментов.