JSONPath: извлечение данных из JSON
Синтаксис JSONPath, запросы к JSON, примеры использования, отличие от jq, практические задачи.
Введение
Современные API возвращают вложенные JSON-структуры на десятки уровней: объекты внутри массивов внутри объектов. Когда нужно вытащить конкретное поле или коллекцию значений, навигация вручную через точку и квадратные скобки становится утомительной. На помощь приходит JSONPath — язык запросов к JSON, аналог XPath для XML. С его помощью можно извлекать данные по шаблонам, фильтровать массивы и обходить произвольные деревья. В этой статье разберём синтаксис JSONPath, примеры запросов и частые сценарии использования.
Что такое JSONPath
JSONPath — это язык запросов, созданный Штефаном Гёсснером в 2007 году. Он позволяет обращаться к элементам JSON через путь, похожий на путь файловой системы, но с поддержкой wildcards, фильтров и срезов массивов. JSONPath реализован во множестве библиотек для JavaScript, Python, Java, Go, PHP и других языков. Стандартизация формата была завершена в IETF RFC 9535 в 2024 году, что устранило диалектные различия между реализациями.
Пример JSON, на котором будем тренироваться:
{
"store": {
"books": [
{ "title": "Война и мир", "author": "Толстой", "price": 1200 },
{ "title": "Анна Каренина", "author": "Толстой", "price": 950 },
{ "title": "Идиот", "author": "Достоевский", "price": 1100, "isbn": "978-5-389" }
],
"magazines": [
{ "title": "Наука и жизнь", "issue": 12 }
]
}
}Базовый синтаксис
JSONPath использует два стиля записи: dot-notation($.store.books[0].title) и bracket-notation($['store']['books'][0]['title']). Первый компактнее, второй позволяет использовать ключи со спецсимволами. Символ $ обозначает корень JSON.
| Символ | Значение | Пример |
|---|---|---|
$ | Корень документа | $ |
. | Дочерний узел | $.store |
.. | Рекурсивный спуск | $..author |
* | Wildcard — любой элемент | $.store.* |
[n] | Индекс массива | $..books[0] |
[a:b] | Срез массива | $..books[0:2] |
[?expr] | Фильтр | $..books[?@.price<1000] |
Примеры запросов
Получение всех заголовков книг
$..books[*].title
// Результат:
// ["Война и мир", "Анна Каренина", "Идиот"]Все авторы (рекурсивный поиск)
$..author
// Результат:
// ["Толстой", "Толстой", "Достоевский"]Две точки .. означают «искать на любой глубине». Это удобно, когда структура может меняться, а поле нужно найти в любом месте.
Фильтрация по условию
$..books[?@.price < 1000].title
// Результат:
// ["Анна Каренина"]Символ @ обозначает текущий элемент массива. В фильтрах поддерживаются операторы сравнения (==, !=, <,>), логические (&&, ||) и функции (length(), contains()).
Срезы массива
$..books[0:2] // первые две книги
$..books[-1] // последняя книга
$..books[1:] // все книги со второйСрезы работают как в Python: [start:end:step]. Отрицательные индексы отсчитываются с конца массива.
Условие на существование поля
$..books[?@.isbn].title
// Результат:
// ["Идиот"]Этот запрос возвращает только те книги, у которых есть поле isbn. Полезно для фильтрации объектов с необязательными полями.
Фильтры и выражения
Фильтры — самая мощная часть JSONPath. Внутри квадратных скобок с вопросительным знаком можно писать выражения любой сложности:
[?@.price > 1000 && @.author == 'Толстой']— книги Толстого дороже 1000 рублей.[?@.title contains 'Анна']— книги с «Анна» в названии (не во всех реализациях).[?@.tags.length() > 3]— объекты с более чем тремя тегами.[?(@.price + @.tax) < 2000]— арифметика в фильтрах.
Синтаксис фильтров различается между реализациями: старые версии не поддерживаютcontains как оператор, в новых появился in иmatches. Стандарт RFC 9535 унифицировал эти возможности.
JSONPath vs jq
Часто JSONPath сравнивают с jq — популярной утилитой командной строки для запросов к JSON. У них разная философия: JSONPath — компактный язык путей, встроенный в библиотеки; jq — полноценный функциональный язык с переменными, функциями и конвейерами.
| Критерий | JSONPath | jq |
|---|---|---|
| Сложность обучения | Низкая | Средняя |
| Выразительность | Средняя | Высокая |
| Встроен в библиотеки | Да | Нет (CLI) |
| Трансформация данных | Ограниченная | Полная |
| Фильтры и условия | Базовые | Богатые |
| Применение | Веб-приложения, API | Скрипты, CLI |
Для большинства задач извлечения данных JSONPath достаточно. Если нужно делать сложную трансформацию — группировку, агрегацию, маппинг — jq удобнее.
Применение JSONPath
- Тестирование API — в Postman и REST Assured JSONPath используется для проверок ответов. Например, проверить, что
$.data[0].idравен ожидаемому значению. - Конфигурация observability — Datadog, Splunk, Logstash применяют JSONPath для извлечения метрик из логов в JSON-формате.
- JSON-логирование — при анализе структурированных логов часто нужно вытащить поле по пути, не зная заранее глубину вложенности.
- Мониторинг событий — вебхуки и системы оповещения используют JSONPath для извлечения значений из payload.
- Динамические правила доступа — в некоторых IAM-системах политики описываются через JSONPath к полям запроса.
Инструменты для работы с JSONPath
Онлайн-инструмент
Для тестирования запросов используйте нашJSONPath Finder. Вставляете JSON, вводите путь — инструмент подсвечивает совпадающие элементы прямо в дереве. Это удобно для отладки сложных фильтров и обучения синтаксису.
Библиотеки
- JavaScript —
jsonpath-plus(полная поддержка стандарта),jsonpath(старый). - Python —
jsonpath-ng,jsonpath2. - Java —
JsonPathот Jayway. - Go —
github.com/PaesslerAG/jsonpath. - .NET —
Newtonsoft.Jsonс методомSelectToken.
Пример в JavaScript
import { JSONPath } from 'jsonpath-plus';
const data = { store: { books: [/* ... */] } };
const titles = JSONPath({ path: '$..books[?@.price < 1000].title', json: data });
console.log(titles); // ["Анна Каренина"]Производительность и ограничения
JSONPath не бесплатный: рекурсивный спуск .. обходит всё дерево, что может быть медленным на больших документах. Фильтры с регулярными выражениями или сложными условиями тоже замедляют запрос. Для высоконагруженных систем, где запросы выполняются часто, кэшируйте распарсенный JSON или используйте прямую навигацию через точку.
JSONPath не предназначен для модификации данных — только для извлечения. Если нужно изменить поле по пути, используйте специализированные библиотеки вродеimmutable-json-patch или реализуйте обход вручную.
Лучшие практики
- Предпочитайте
$.fieldвместо$..field, когда знаете структуру — это быстрее. - Используйте фильтры с осторожностью: чем сложнее выражение, тем медленнее запрос.
- Тестируйте запросы на реальных данных перед использованием в продакшне.
- Документируйте неочевидные запросы — JSONPath читается хуже, чем обычный код.
- Помните, что разные реализации могут поддерживать разный набор функций.
- Для больших JSON используйте стриминговые парсеры, а не загружайте весь документ в память.
Связанные инструменты
После извлечения данных через JSONPath их часто нужно отформатировать или преобразовать. Для этого подходят JSON форматтердля красивого отображения, JSON в CSV для табличного экспорта и JSON в TypeScript для генерации типов. Если данные пришли в минифицированном виде, сначала применитеформатирование, а потом — JSONPath.
Заключение
JSONPath — компактный и выразительный язык для извлечения данных из JSON. Он незаменим в тестировании API, анализе логов и автоматизации. Базовый синтаксис осваивается за час, а продвинутые фильтры покрывают большинство сценариев. Для экспериментов используйте JSONPath Finder от ConvertHub — он работает локально и подсвечивает совпадения в дереве. Если нужно больше выразительности — присмотритесь к jq, но для типичных задач JSONPath хватает с запасом.
Попробуйте эти инструменты
Похожие статьи
JSON vs XML — какое выбрать для проекта
Сравнение JSON и XML: синтаксис, размер, скорость парсинга, читаемость. Когда JSON лучше, а когда XML.
JSON форматтер: зачем нужен и как использовать
Что такое форматирование JSON, отступы и пробелы, валидация, minify vs beautify, лучшие практики.
CSV в JSON: конвертация и когда нужна
Как преобразовать CSV в JSON, структура данных, обработка больших файлов, использование в JavaScript.
YAML — конфигурационный формат: полный гид
Синтаксис YAML, отступы, типы данных, отличие от JSON, использование в Docker, Kubernetes, CI/CD.