JSONPath
JSONPath — это язык запросов (выражений) для извлечения данных из документов в формате JSON (JavaScript Object Notation). Он предоставляет синтаксис для навигации по иерархической структуре JSON и выбора конкретных элементов, их наборов или значений, аналогично тому, как XPath используется для XML-документов. JSONPath не является официальным стандартом, но существует несколько реализаций для различных языков программирования, основанных на общей спецификации, предложенной Стефаном Гёсснером в 2007 году.
История и происхождение
Концепция JSONPath была впервые предложена Стефаном Гёсснером (Stefan Gössner) в 2007 году в статье «JSONPath — XPath for JSON». Основной целью было создание простого и интуитивно понятного инструмента для запросов к данным в формате JSON, который быстро набирал популярность как альтернатива XML в веб-разработке и API. Гёсснер вдохновлялся синтаксисом XPath, но адаптировал его под структуру JSON, используя точечную нотацию (dot notation) и скобочную нотацию (bracket notation), привычную для JavaScript.
Первоначальная реализация была написана на JavaScript. Впоследствии появились библиотеки для других языков, таких как Python (jsonpath-ng, jsonpath-rw), Java (Jayway JsonPath), PHP (JsonPath), Ruby, Go и .NET. В 2024 году была опубликована спецификация IETF RFC 9535 «JSONPath: Query Expressions for JSON», которая формализовала синтаксис и семантику языка, стремясь унифицировать существующие реализации.
Синтаксис и основные конструкции
JSONPath использует выражения, которые начинаются с символа $, обозначающего корневой элемент документа JSON. Далее следуют селекторы, разделённые точками или квадратными скобками.
Основные селекторы
- Корневой элемент:
$— ссылка на весь документ. - Дочерний элемент (точка):
.key— выбор свойства с именемkeyу текущего объекта. - Дочерний элемент (скобки):
['key']— альтернативный синтаксис, позволяющий использовать ключи с пробелами или специальными символами. - Индекс массива:
[index]— выбор элемента массива по числовому индексу (начиная с 0). - Рекурсивный спуск:
..— поиск всех элементов с указанным именем на любом уровне вложенности. - Подстановочный знак:
*— выбор всех дочерних элементов объекта или всех элементов массива. - Фильтр:
[?(expression)]— выбор элементов, удовлетворяющих логическому условию.
Примеры выражений
Рассмотрим следующий JSON-документ:
``json { "store": { "book": [ { "title": "Война и мир", "price": 500 }, { "title": "Преступление и наказание", "price": 400 } ], "bicycle": { "color": "красный", "price": 15000 } } } ``
| Выражение JSONPath | Результат |
|---|---|
$.store.book | Массив книг. |
$.store.book[0] | Первая книга (объект). |
$.store.book[0].title | "Война и мир" |
$.store.book[*].title | Массив названий всех книг: ["Война и мир", "Преступление и наказание"] |
$..price | Массив всех цен: [500, 400, 15000] |
$.store.book[?(@.price < 450)] | Массив книг, цена которых меньше 450. |
$.store.book[?(@.price >= 400)] | Массив книг, цена которых больше или равна 400. |
$..book[?(@.title =~ /Преступление/i)] | Массив книг, название которых соответствует регулярному выражению (регистронезависимо). |
Операторы в фильтрах
Фильтры [?(expression)] поддерживают следующие операторы:
- Сравнение:
==(равно),!=(не равно),<,>,<=,>=. - Логические:
&&(и),||(или),!(не). - Наличие:
@.property(проверка существования свойства). - Регулярные выражения:
=~(сопоставление с регулярным выражением). Поддержка зависит от реализации. - Текущий элемент:
@— ссылка на текущий обрабатываемый элемент в фильтре.
Реализации и стандартизация
Основные библиотеки
- JavaScript:
jsonpath(npm),jsonpath-plus. - Java:
Jayway JsonPath(наиболее популярная),JsonPathот Apache. - Python:
jsonpath-ng(расширенная поддержка),jsonpath-rw. - PHP:
JsonPath(часть библиотекиflow/jsonpath). - Go:
jsonpath(встроенная поддержка вkubectl). - .NET:
JsonPath.Net(реализация от Newtonsoft.Json).
RFC 9535
В феврале 2024 года был опубликован RFC 9535 «JSONPath: Query Expressions for JSON», который определил единый стандарт для языка. Основные положения стандарта:
- Поддержка точечной и скобочной нотации.
- Определение фильтров с использованием
@для текущего узла. - Поддержка рекурсивного спуска (
..). - Определение нормализованного пути для сравнения результатов.
- Уточнение семантики для работы с пустыми массивами и отсутствующими ключами.
Стандарт не включает поддержку функций (например, min(), max()), которые присутствуют в некоторых расширениях, но оставляет возможность для их добавления в будущих версиях.
Применение
JSONPath широко используется в различных областях, связанных с обработкой данных:
- API-тестирование: Для извлечения и проверки значений из ответов REST API (например, в инструментах Postman, SoapUI, Newman).
- Обработка данных: Для фильтрации и трансформации JSON-документов в ETL-процессах (Extract, Transform, Load).
- Конфигурационные файлы: Для доступа к параметрам в конфигурациях, написанных на JSON (например, в Kubernetes, Docker Compose).
- Инструменты командной строки:
jq(хотя использует собственный язык, его синтаксис частично пересекается с JSONPath),kubectl get ... -o jsonpath='...'(встроенная поддержка в Kubernetes). - Базы данных: Некоторые NoSQL базы данных (например, MongoDB, Couchbase) поддерживают запросы, основанные на синтаксисе JSONPath.
- Веб-разработка: Для динамического обновления частей веб-страницы на основе JSON-данных, полученных от сервера.
Критика и ограничения
- Неоднозначность реализаций: До появления RFC 9535 различные реализации могли по-разному интерпретировать один и тот же запрос, особенно в сложных случаях (например, при фильтрации с рекурсивным спуском).
- Отсутствие агрегатных функций: Стандартный JSONPath не поддерживает вычисление сумм, средних значений, минимумов и максимумов. Для этого требуются внешние инструменты или расширения.
- Сложность с регулярными выражениями: Поддержка регулярных выражений в фильтрах не является обязательной по стандарту и может отличаться в разных реализациях.
- Производительность: Для очень больших JSON-документов (сотни мегабайт и более) рекурсивный спуск (
..) может быть медленным, так как требует обхода всего дерева.
Сравнение с XPath
JSONPath часто сравнивают с XPath, который используется для XML. Основные различия:
| Характеристика | JSONPath | XPath |
|---|---|---|
| Целевой формат | JSON | XML |
| Синтаксис | Точечная/скобочная нотация (JavaScript-подобный) | Путь с косой чертой (Unix-подобный) |
| Корневой элемент | $ | / |
| Текущий элемент | @ | . |
| Рекурсивный спуск | .. | // |
| Подстановочный знак | * | * |
| Фильтры | [?(expression)] | [predicate] |
| Функции | Отсутствуют в стандарте | Множество встроенных функций (string, number, boolean) |
| Пространства имён | Не поддерживаются | Поддерживаются |
Интересные факты
- Несмотря на то, что JSONPath был создан в 2007 году, его популярность резко возросла с распространением REST API и микросервисной архитектуры в 2010-х годах.
- Встроенная поддержка JSONPath в
kubectl(инструменте командной строки Kubernetes) является одной из самых частых причин, по которой разработчики знакомятся с этим языком. - Существуют онлайн-инструменты (например, JSONPath.com, JSONPath Finder), которые позволяют интерактивно тестировать выражения JSONPath на произвольных JSON-документах.
Источники
- Stefan Gössner. «JSONPath — XPath for JSON» (2007).
- RFC 9535: «JSONPath: Query Expressions for JSON» (2024).
- Документация библиотеки Jayway JsonPath (Java).
- Документация инструмента командной строки
kubectlпо использованию JSONPath. - Сравнительный анализ JSONPath и XPath в технической документации.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →