Руководство по запросам JSONPath: извлекайте данные как профессионал
JSONPath — это язык запросов для JSON, аналогичный тому, как XPath работает для XML. Когда вы имеете дело со сложными, глубоко вложенными JSON-ответами от API, JSONPath позволяет извлечь именно те данные, которые вам нужны, без написания циклов и условий. Это руководство охватывает синтаксис, операторы и реальные паттерны использования.
Зачем нужен JSONPath?
Рассмотрим типичный ответ API с вложенными данными:
{
"store": {
"books": [
{ "title": "Clean Code", "author": "Robert Martin", "price": 32.99, "tags": ["programming", "best-practices"] },
{ "title": "Design Patterns", "author": "Gang of Four", "price": 44.99, "tags": ["programming", "architecture"] },
{ "title": "The Pragmatic Programmer", "author": "Hunt & Thomas", "price": 39.99, "tags": ["programming", "career"] }
],
"music": [
{ "title": "Kind of Blue", "artist": "Miles Davis", "price": 12.99 }
]
}
}
Чтобы получить все названия книг, можно написать цикл — или использовать JSONPath: $.store.books[*].title
Базовый синтаксис
| Выражение | Описание |
|---|---|
$ | Корневой объект |
. | Оператор дочернего элемента |
.. | Рекурсивный спуск (поиск на всех уровнях) |
[*] | Подстановочный символ (все элементы) |
[n] | Индекс массива (с нуля) |
[n,m] | Несколько индексов |
[start:end:step] | Срез массива |
[?()] | Выражение-фильтр |
@ | Текущий элемент (в фильтрах) |
Точечная нотация и скобочная нотация
Обе нотации обращаются к свойствам, но скобочная нотация необходима для специальных символов:
# Точечная нотация
$.store.books[0].title
# Скобочная нотация (эквивалент)
$['store']['books'][0]['title']
# Обязательна для ключей со специальными символами
$['store']['price-range']
Операции с массивами
Индексация
$.store.books[0] # Первая книга
$.store.books[-1] # Последняя книга
$.store.books[0,2] # Первая и третья книги
Срезы
$.store.books[0:2] # Первые две книги (индексы 0 и 1)
$.store.books[1:] # Все книги, кроме первой
$.store.books[:2] # Первые две книги
$.store.books[::2] # Каждая вторая книга
Подстановочные символы
$.store.books[*].title # Все названия книг
$.store.* # Все коллекции магазина (books, music)
$..title # Все заголовки на любом уровне вложенности
$..price # Все цены на любом уровне вложенности
Оператор рекурсивного спуска (..) особенно мощный для извлечения значений независимо от их положения в иерархии.
Выражения-фильтры
Фильтры выбирают элементы на основе условий:
# Книги дешевле $40
$.store.books[?(@.price < 40)]
# Книги конкретного автора
$.store.books[?(@.author == 'Robert Martin')]
# Книги с более чем 2 тегами
$.store.books[?(@.tags.length > 2)]
# Книги, у которых есть свойство 'price'
$.store.books[?(@.price)]
Комбинирование фильтров
# Книги дешевле $40 с тегом programming
$.store.books[?(@.price < 40 && @.tags[0] == 'programming')]
Практические примеры
Извлечение из ответов API
GitHub API — получить все имена репозиториев:
$[*].name
Weather API — получить сегодняшнюю температуру:
$.daily[0].temp.day
API электронной коммерции — получить все изображения товаров:
$.products[*].images[0].url
Извлечение из конфигураций
Docker Compose — получить все имена сервисов:
$.services.*~
Package.json — получить все имена зависимостей:
$.dependencies.*~
JSONPath и jq
JSONPath и jq — оба инструменты запросов к JSON, но используются в разных контекстах:
| Возможность | JSONPath | jq |
|---|---|---|
| Среда | Библиотеки, API | Командная строка |
| Синтаксис | Вдохновлён XPath | Собственный функциональный |
| Трансформация | Только запросы | Запросы + трансформация |
| Стандарт | RFC 9535 | Де-факто стандарт |
Для обработки JSON в командной строке jq более мощный. Для встраивания запросов в приложения или использования в веб-инструментах JSONPath поддерживается шире.
Попробуйте выражения JSONPath интерактивно с нашим JSON Path Explorer. Вставьте ваш JSON, напишите запрос и мгновенно увидите результаты.
Примеры реализации
JavaScript (jsonpath-plus)
const { JSONPath } = require('jsonpath-plus');
const result = JSONPath({
path: '$.store.books[?(@.price < 40)].title',
json: data
});
// ["Clean Code", "The Pragmatic Programmer"]
Python (jsonpath-ng)
from jsonpath_ng import parse
expr = parse('$.store.books[*].title')
titles = [match.value for match in expr.find(data)]
RFC 9535: стандарт JSONPath
В феврале 2024 года JSONPath был официально стандартизирован как RFC 9535. Это устранило исторические несоответствия между реализациями. Ключевые стандартизированные поведения:
- Индексы массивов начинаются с 0
- Выражения-фильтры используют
@для текущего элемента - Сравнение строк чувствительно к регистру
- Результат всегда представляет собой массив совпавших значений
При выборе библиотеки JSONPath отдавайте предпочтение тем, которые поддерживают RFC 9535, для согласованного поведения.
Часто задаваемые вопросы
В чём разница между JSONPath и JSON Pointer?
JSONPath — это язык запросов, который может находить несколько значений с помощью подстановочных символов и фильтров. JSON Pointer (RFC 6901) — это простой синтаксис пути, который указывает ровно на одно значение: /store/books/0/title. Используйте JSONPath, когда нужен поиск или фильтрация; используйте JSON Pointer, когда знаете точный путь.
Может ли JSONPath изменять данные JSON?
Стандартный JSONPath предназначен только для чтения — он извлекает, но не изменяет данные. Некоторые библиотеки расширяют JSONPath операциями set/delete, но они нестандартны. Для трансформаций используйте jq (командная строка) или пишите код приложения. Для просмотра и изучения структуры JSON наш JSON Formatter поможет вам понять данные перед написанием запросов.
Связанные ресурсы
- JSON Path Explorer — Тестируйте выражения JSONPath в браузере
- Лучшие практики форматирования JSON — Структурируйте ваш JSON для удобства запросов
- Руководство по валидации JSON Schema — Валидируйте структуру, которую ожидают ваши JSONPath-запросы