Открыть сервис

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. Основные различия:

ХарактеристикаJSONPathXPath
Целевой форматJSONXML
СинтаксисТочечная/скобочная нотация (JavaScript-подобный)Путь с косой чертой (Unix-подобный)
Корневой элемент$/
Текущий элемент@.
Рекурсивный спуск..//
Подстановочный знак**
Фильтры[?(expression)][predicate]
ФункцииОтсутствуют в стандартеМножество встроенных функций (string, number, boolean)
Пространства имёнНе поддерживаютсяПоддерживаются

Интересные факты

  • Несмотря на то, что JSONPath был создан в 2007 году, его популярность резко возросла с распространением REST API и микросервисной архитектуры в 2010-х годах.
  • Встроенная поддержка JSONPath в kubectl (инструменте командной строки Kubernetes) является одной из самых частых причин, по которой разработчики знакомятся с этим языком.
  • Существуют онлайн-инструменты (например, JSONPath.com, JSONPath Finder), которые позволяют интерактивно тестировать выражения JSONPath на произвольных JSON-документах.

Источники

  1. Stefan Gössner. «JSONPath — XPath for JSON» (2007).
  2. RFC 9535: «JSONPath: Query Expressions for JSON» (2024).
  3. Документация библиотеки Jayway JsonPath (Java).
  4. Документация инструмента командной строки kubectl по использованию JSONPath.
  5. Сравнительный анализ JSONPath и XPath в технической документации.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →