DevToys Pro

бесплатные веб-инструменты для разработчиков

Блог
Оцените нас:
Попробуйте расширение для браузера:
← Назад к блогу

Шпаргалка по JSONPath для отладки API

15 мин чтения

JSONPath — это язык запросов для JSON, похожий на XPath для XML. Он позволяет извлекать конкретные данные из сложных JSON структур, используя краткие выражения путей. Это особенно полезно при отладке ответов API, обработке больших наборов данных или извлечении значений из вложенных объектов.

Эта шпаргалка охватывает основные операторы JSONPath с практическими примерами, ориентированными на сценарии отладки API.

Быстрая справка

ОператорОписаниеПример
$Корневой объект$.user
@Текущий объект (в фильтрах)@.price
.Оператор дочернего элемента$.user.name
..Рекурсивный спуск$..email
*Подстановочный знак (все элементы)$.users[*].name
[]Индекс массива$.items[0]
[start:end]Срез массива$.items[0:3]
[?()]Выражение фильтра$.items[?(@.price < 10)]

Примеры данных

Мы будем использовать эту структуру ответа API для примеров:

{
  "status": "success",
  "user": {
    "id": 101,
    "name": "Alice Johnson",
    "email": "alice@example.com",
    "roles": ["admin", "editor"]
  },
  "products": [
    {
      "id": 1,
      "name": "Laptop",
      "price": 999,
      "inStock": true,
      "tags": ["electronics", "computers"]
    },
    {
      "id": 2,
      "name": "Mouse",
      "price": 25,
      "inStock": true,
      "tags": ["electronics", "accessories"]
    },
    {
      "id": 3,
      "name": "Monitor",
      "price": 349,
      "inStock": false,
      "tags": ["electronics", "displays"]
    }
  ],
  "metadata": {
    "timestamp": "2026-01-11T10:00:00Z",
    "version": "1.0",
    "pagination": {
      "page": 1,
      "pageSize": 10,
      "total": 45
    }
  }
}

Базовый выбор

Корень и прямой доступ

JSONPathРезультат
$Весь документ
$.status"success"
$.user.name"Alice Johnson"
$.user.email"alice@example.com"

Доступ к вложенным объектам

JSONPathРезультат
$.metadata.version"1.0"
$.metadata.pagination.page1
$.metadata.pagination.total45

Операции с массивами

Индексация массива

JSONPathРезультат
$.products[0]Первый продукт (Laptop)
$.products[1].name"Mouse"
$.products[-1]Последний продукт (Monitor)
$.user.roles[0]"admin"

Срезы массивов

JSONPathРезультат
$.products[0:2]Первые два продукта
$.products[1:]Все продукты кроме первого
$.products[:2]Первые два продукта
$.products[-2:]Последние два продукта

Подстановочные знаки

JSONPathРезультат
$.products[*].nameВсе названия продуктов
$.products[*].priceВсе цены продуктов: [999, 25, 349]
$.products[*].idВсе ID продуктов: [1, 2, 3]

Глубокое сканирование (Рекурсивный спуск)

Оператор .. ищет по всему дереву документа:

JSONPathРезультат
$..nameВсе поля "name" на любом уровне
$..priceВсе поля "price": [999, 25, 349]
$..idВсе поля "id": [101, 1, 2, 3]
$..tags[0]Первый тег всех продуктов

Выражения фильтров

Выражения фильтров используют синтаксис [?()] с @, указывающим на текущий элемент:

Операторы сравнения

JSONPathРезультат
$.products[?(@.price < 100)]Продукты дешевле $100 (Mouse)
$.products[?(@.price >= 300)]Продукты от $300+ (Laptop, Monitor)
$.products[?(@.inStock == true)]Продукты в наличии (Laptop, Mouse)
$.products[?(@.inStock != true)]Продукты не в наличии (Monitor)

Логические операторы

JSONPathРезультат
$.products[?(@.price < 100 && @.inStock)]Дёшево + в наличии (Mouse)
$.products[?(@.price > 500 || !@.inStock)]Дорого или нет в наличии

Проверки существования

JSONPathРезультат
$.products[?(@.tags)]Продукты с полем tags
$..products[?(@.discount)]Продукты с полем discount (нет)

Реальные сценарии отладки API

Сценарий 1: Извлечение всех сообщений об ошибках

{
  "results": [
    {"status": "success", "data": {...}},
    {"status": "error", "message": "Invalid token"},
    {"status": "success", "data": {...}},
    {"status": "error", "message": "Database timeout"}
  ]
}

// Извлечь все сообщения об ошибках
$.results[?(@.status == 'error')].message

// Результат: ["Invalid token", "Database timeout"]

Сценарий 2: Поиск элементов с конкретными тегами

// Найти все продукты с тегом "electronics"
$.products[?(@.tags[*] == 'electronics')]

// Найти продукты с ОБОИМИ тегами "electronics" И "computers"
$.products[?(@.tags[*] == 'electronics' && @.tags[*] == 'computers')]

Сценарий 3: Извлечение вложенных данных пагинации

{
  "response": {
    "data": [...],
    "meta": {
      "pagination": {
        "current_page": 2,
        "total_pages": 10,
        "next_page": 3
      }
    }
  }
}

// Извлечь информацию о пагинации
$.response.meta.pagination
// или использовать глубокое сканирование
$..pagination

Сценарий 4: Фильтрация многоуровневых данных

{
  "users": [
    {
      "name": "Alice",
      "orders": [
        {"id": 1, "total": 100, "paid": true},
        {"id": 2, "total": 50, "paid": false}
      ]
    },
    {
      "name": "Bob",
      "orders": [
        {"id": 3, "total": 200, "paid": true}
      ]
    }
  ]
}

// Получить все неоплаченные заказы (любого пользователя)
$..orders[?(@.paid == false)]

// Получить пользователей с неоплаченными заказами
$.users[?(@.orders[?(@.paid == false)])]

Сценарий 5: Извлечение ID для массовых операций

// Получить ID всех продуктов в наличии дешевле $100
$.products[?(@.inStock && @.price < 100)].id

// Получить ID всех продуктов
$.products[*].id

// Получить ID используя глубокое сканирование (работает даже если структура меняется)
$..products[*].id

Продвинутые паттерны

Комбинирование нескольких фильтров

// Продукты: в наличии, дешевле $500, с тегом "electronics"
$.products[?(
  @.inStock == true &&
  @.price < 500 &&
  @.tags[*] == 'electronics'
)]

Сопоставление с регулярными выражениями (зависит от реализации)

// Продукты где название начинается с "M"
$.products[?(@.name =~ /^M/)]

// Пользователи с .com email адресами
$.users[?(@.email =~ /\.com$/)]

Примечание: Поддержка regex зависит от реализации JSONPath.

Выражения скриптов (Продвинутые)

// Продукты с ценой в пределах 10% от средней
$.products[?(@.price < 400)]

// Вычислить длину
$.products[?(@.tags.length > 1)]

Распространённые подводные камни

Подводный камень 1: Забыли корень

// Неправильно - нет корня
products[0].name

// Правильно
$.products[0].name

Подводный камень 2: Путаница между . и ..

// Одна точка - прямой дочерний элемент
$.user.name  // Получает только user.name

// Двойная точка - рекурсивный поиск
$..name  // Получает ВСЕ поля "name" на любом уровне

Подводный камень 3: Подстановочный знак vs фильтр

// Подстановочный знак - получает все элементы
$.products[*].name

// Фильтр - получает элементы, удовлетворяющие условию
$.products[?(@.inStock)].name

Подводный камень 4: Индекс массива вне границ

// Если массив имеет 3 элемента:
$.products[10]  // Возвращает undefined/null, не ошибку

// Используйте фильтры или подстановочные знаки для безопасности
$.products[?(@.id == 10)]

Различия в реализациях

Реализации JSONPath отличаются в зависимости от языков и библиотек:

JavaScript (библиотека jsonpath)

const jp = require('jsonpath');

const result = jp.query(data, '$.products[?(@.price < 100)]');
console.log(result);

Python (jsonpath-ng)

from jsonpath_ng import parse

expression = parse('$.products[*].name')
matches = [match.value for match in expression.find(data)]

Go (gjson)

import "github.com/tidwall/gjson"

result := gjson.Get(jsonString, "products.#(price<100).name")
fmt.Println(result.String())

Тестирование выражений JSONPath

Используйте DevToys Pro JSONPath тестер для:

  • Тестирования выражений на реальных ответах API
  • Отладки сложных условий фильтров
  • Валидации синтаксиса путей перед реализацией в коде
  • Экспериментов с различными операторами и комбинациями
  • Сравнения результатов разных подходов к запросам

Лучшие практики

1. Начинайте с простого, затем уточняйте

// Шаг 1: Получить все продукты
$.products

// Шаг 2: Получить все названия продуктов
$.products[*].name

// Шаг 3: Фильтровать по условию
$.products[?(@.inStock)].name

2. Используйте фильтры вместо сложной индексации

// Менее поддерживаемо - предполагает порядок
$.products[2].name

// Более поддерживаемо - находит по свойству
$.products[?(@.id == 3)].name

3. Используйте глубокое сканирование осторожно

// Может быть медленным на больших документах
$..price

// Предпочитайте конкретные пути когда возможно
$.products[*].price

4. Обрабатывайте отсутствующие данные

// Проверяйте существование перед доступом
$.user.profile?.address?.city

// Или используйте фильтр существования
$.users[?(@.profile && @.profile.address)]

Заключение

JSONPath предоставляет мощный, краткий синтаксис для запросов к JSON структурам. Ключевые выводы:

  • Используйте $ для корня, . для доступа к дочерним элементам, .. для рекурсивного поиска
  • Операции с массивами поддерживают индексацию, срезы и подстановочные знаки ([0], [0:3], [*])
  • Выражения фильтров [?()] позволяют условный выбор
  • Комбинируйте операторы для сложных запросов: $.products[?(@.price < 100)].name
  • Тестируйте выражения перед развёртыванием в production
  • Учитывайте различия реализаций в разных языках

Для тестирования и отладки выражений JSONPath используйте JSONPath тестер для валидации запросов на реальных ответах API и экспериментов с различными стратегиями выбора.