JSONPath: Поиск путей и навигация по JSON данным
Полное руководство по JSONPath - мощному языку запросов для поиска и извлечения данных из JSON структур.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# JSONPath: Поиск путей и навигация по JSON данным
JSONPath - это мощный язык запросов для JSON, подобный XPath для XML. Он позволяет извлекать и манипулировать данными в сложных JSON структурах. В этом подробном руководстве мы изучим все возможности JSONPath.
Что такое JSONPath?
JSONPath - это язык запросов, который позволяет выбирать и извлекать данные из JSON документов. Он был создан Стефаном Гёсснером как альтернатива XPath для JSON.
Базовый синтаксис
$ - корневой элемент
. - текущий элемент
.. - рекурсивный поиск
- wildcard (любой элемент)
[] - индекс массива или фильтр
Примеры данных для работы
Будем использовать следующий JSON для примеров:
{
"магазин": {
"название": "Книжный мир",
"книги": [
{
"категория": "художественная",
"автор": "Лев Толстой",
"название": "Война и мир",
"isbn": "978-5-17-098352-4",
"цена": 500,
"наличие": true
},
{
"категория": "художественная",
"автор": "Федор Достоевский",
"название": "Преступление и наказание",
"isbn": "978-5-17-098353-1",
"цена": 450,
"наличие": true
},
{
"категория": "техническая",
"автор": "Брюс Эккель",
"название": "Философия Java",
"isbn": "978-5-496-00739-5",
"цена": 800,
"наличие": false
},
{
"категория": "техническая",
"автор": "Роберт Мартин",
"название": "Чистый код",
"isbn": "978-5-496-00487-5",
"цена": 650,
"наличие": true
}
],
"велосипеды": [
{
"тип": "горный",
"производитель": "Giant",
"модель": "Talon 1",
"цена": 45000,
"цвет": "черный"
},
{
"тип": "шоссейный",
"производитель": "Trek",
"модель": "Domane AL 2",
"цена": 65000,
"цвет": "красный"
}
]
}
}
Базовые операции
Получение корневого элемента
// JSONPath запрос
$
// Результат: весь JSON документ
Доступ к свойству
// Название магазина
$.магазин.название
// Результат
"Книжный мир"
Доступ к массиву
// Все книги
$.магазин.книги
// Результат: массив всех книг
[{...}, {...}, {...}, {...}]
Доступ к элементу массива по индексу
// Первая книга
$.магазин.книги[0]
// Результат
{
"категория": "художественная",
"автор": "Лев Толстой",
"название": "Война и мир",
"isbn": "978-5-17-098352-4",
"цена": 500,
"наличие": true
}
// Последняя книга
$.магазин.книги[-1]
// Вторая и третья книги
$.магазин.книги[1:3]
Wildcard (Подстановочные знаки)
Все элементы на уровне
// Все свойства магазина
$.магазин.
// Результат: массив всех значений
["Книжный мир", [...книги...], [...велосипеды...]]
Все элементы в массиве
// Все книги
$.магазин.книги[]
// Названия всех книг
$.магазин.книги[].название
// Результат
[
"Война и мир",
"Преступление и наказание",
"Философия Java",
"Чистый код"
]
Рекурсивный поиск
Поиск по всему документу
// Все цены в документе
$..цена
// Результат
[500, 450, 800, 650, 45000, 65000]
// Все названия
$..название
// Результат
[
"Книжный мир",
"Война и мир",
"Преступление и наказание",
"Философия Java",
"Чистый код"
]
Фильтры
Синтаксис фильтров
Фильтры используют ?(выражение) синтаксис.
Сравнение значений
// Книги дороже 500 рублей
$.магазин.книги[?(@.цена > 500)]
// Результат
[
{
"категория": "техническая",
"автор": "Брюс Эккель",
"название": "Философия Java",
"цена": 800,
"наличие": false
},
{
"категория": "техническая",
"автор": "Роберт Мартин",
"название": "Чистый код",
"цена": 650,
"наличие": true
}
]
Проверка на равенство
// Технические книги
$.магазин.книги[?(@.категория == 'техническая')]
// Книги в наличии
$.магазин.книги[?(@.наличие == true)]
// Книги не в наличии
$.магазин.книги[?(@.наличие == false)]
Проверка существования свойства
// Элементы с ISBN
$.магазин.книги[?(@.isbn)]
// Элементы без ISBN
$.магазин.велосипеды[?(!@.isbn)]
Логические операторы
// И (AND)
$.магазин.книги[?(@.цена > 400 && @.наличие == true)]
// ИЛИ (OR)
$.магазин.книги[?(@.цена < 500 || @.категория == 'техническая')]
// НЕ (NOT)
$.магазин.книги[?(!(@.цена > 700))]
Регулярные выражения
// Книги, название которых содержит "код"
$.магазин.книги[?(@.название =~ /код/i)]
// Книги авторов, чья фамилия начинается с "Т"
$.магазин.книги[?(@.автор =~ /^Лев/)]
Срезы массивов
Базовые срезы
// Первые две книги
$.магазин.книги[0:2]
// С третьей до конца
$.магазин.книги[2:]
// Последние две
$.магазин.книги[-2:]
// Все кроме первой и последней
$.магазин.книги[1:-1]
Срезы с шагом
// Каждая вторая книга
$.магазин.книги[::2]
// Результат: 1-я и 3-я книга
[
{"название": "Война и мир", ...},
{"название": "Философия Java", ...}
]
Сложные запросы
Множественные условия
// Доступные технические книги дороже 600
$.магазин.книги[?(@.категория == 'техническая' && @.наличие == true && @.цена > 600)]
// Результат
[
{
"категория": "техническая",
"автор": "Роберт Мартин",
"название": "Чистый код",
"цена": 650,
"наличие": true
}
]
Вложенные запросы
// Сначала фильтруем, потом выбираем поля
$.магазин.книги[?(@.цена < 600)].название
// Результат
[
"Война и мир",
"Преступление и наказание"
]
Использование в коде
JavaScript (с библиотекой JSONPath)
const jsonpath = require('jsonpath');
const данные = {
"магазин": {
"книги": [
{"название": "Война и мир", "цена": 500, "наличие": true},
{"название": "Чистый код", "цена": 650, "наличие": true}
]
}
};
// Простой запрос
const названия = jsonpath.query(данные, '$.магазин.книги[].название');
console.log(названия);
// ["Война и мир", "Чистый код"]
// С фильтром
const дорогиеКниги = jsonpath.query(
данные,
'$.магазин.книги[?(@.цена > 500)]'
);
console.log(дорогиеКниги);
// [{"название": "Чистый код", "цена": 650, "наличие": true}]
// Получение путей
const пути = jsonpath.paths(данные, '$.магазин.книги[].название');
console.log(пути);
// [
// ["$", "магазин", "книги", 0, "название"],
// ["$", "магазин", "книги", 1, "название"]
// ]
// Установка значений
jsonpath.value(данные, '$.магазин.книги[0].цена', 550);
console.log(данные.магазин.книги[0].цена); // 550
Python (с библиотекой jsonpath-ng)
from jsonpath_ng import jsonpath, parse
данные = {
"магазин": {
"книги": [
{"название": "Война и мир", "цена": 500, "наличие": True},
{"название": "Чистый код", "цена": 650, "наличие": True}
]
}
}
# Простой запрос
путь = parse('$.магазин.книги[].название')
совпадения = [match.value for match in путь.find(данные)]
print(совпадения)
# ["Война и мир", "Чистый код"]
# С использованием jsonpath-rw для фильтров
from jsonpath_rw_ext import parse as parse_ext
# Фильтр
путь = parse_ext('$.магазин.книги[?(@.цена > 500)]')
результат = путь.find(данные)
for совпадение in результат:
print(совпадение.value)
PHP
<?php
require 'vendor/autoload.php';
use FlowJSONPathJSONPath;
$данные = json_decode('{
"магазин": {
"книги": [
{"название": "Война и мир", "цена": 500},
{"название": "Чистый код", "цена": 650}
]
}
}');
$jsonPath = new JSONPath($данные);
// Простой запрос
$результат = $jsonPath->find('$.магазин.книги[].название');
print_r($результат->getData());
// Array ( [0] => Война и мир [1] => Чистый код )
// С фильтром
$дорогие = $jsonPath->find('$.магазин.книги[?(@.цена > 500)]');
print_r($дорогие->getData());
?>
Продвинутые техники
Агрегация данных
// Сумма всех цен книг
const цены = jsonpath.query(данные, '$.магазин.книги[].цена');
const сумма = цены.reduce((acc, цена) => acc + цена, 0);
console.log('Общая стоимость:', сумма);
// Средняя цена
const средняя = сумма / цены.length;
console.log('Средняя цена:', средняя);
Группировка
// Группировка книг по категории
const книги = jsonpath.query(данные, '$.магазин.книги[]');
const поКатегориям = книги.reduce((acc, книга) => {
const категория = книга.категория;
if (!acc[категория]) {
acc[категория] = [];
}
acc[категория].push(книга);
return acc;
}, {});
console.log(поКатегориям);
// {
// "художественная": [...],
// "техническая": [...]
// }
Преобразование данных
// Создание нового объекта с преобразованными данными
const книгиВНаличии = jsonpath.query(
данные,
'$.магазин.книги[?(@.наличие == true)]'
).map(книга => ({
название: книга.название,
автор: книга.автор,
ценаСоСкидкой: книга.цена 0.9
}));
console.log(книгиВНаличии);
Сравнение с другими подходами
JSONPath vs Прямой доступ
// Прямой доступ
const название1 = данные.магазин.книги[0].название;
// JSONPath
const название2 = jsonpath.query(данные, '$.магазин.книги[0].название')[0];
// JSONPath более гибкий для динамических запросов
const путь = пользовательскийВвод; // например, '$.магазин.книги[0].название'
const результат = jsonpath.query(данные, путь);
JSONPath vs jq
# jq (командная строка)
cat данные.json | jq '.магазин.книги[] | select(.цена > 500)'
# Эквивалентный JSONPath
$.магазин.книги[?(@.цена > 500)]
Онлайн инструменты для JSONPath
JSONPath Online Evaluator
URL: jsonpath.comВозможности:
- Интерактивное тестирование
- Подсветка результатов
- Примеры запросов
- Документация
1. Вставить JSON в левую панель
Ввести JSONPath выражение
Увидеть результаты справа
Экспериментировать с запросами
JSONPath Finder
Встроенный в JSON Editor Online - визуальный способ построения JSONPath запросов.
Практические примеры
Пример 1: Поиск пользователей
{
"пользователи": [
{
"id": 1,
"имя": "Иван",
"возраст": 30,
"город": "Москва",
"роли": ["admin", "user"]
},
{
"id": 2,
"имя": "Мария",
"возраст": 25,
"город": "СПб",
"роли": ["user"]
},
{
"id": 3,
"имя": "Петр",
"возраст": 35,
"город": "Москва",
"роли": ["moderator", "user"]
}
]
}
Запросы:
// Все имена
$.пользователи[].имя
// Пользователи старше 25
$.пользователи[?(@.возраст > 25)]
// Пользователи из Москвы
$.пользователи[?(@.город == 'Москва')]
// Администраторы
$.пользователи[?(@.роли[] == 'admin')]
Пример 2: Анализ заказов
{
"заказы": [
{
"id": "ORD001",
"клиент": "Иван",
"товары": [
{"название": "Книга", "цена": 500, "количество": 2},
{"название": "Ручка", "цена": 50, "количество": 5}
],
"статус": "доставлен"
},
{
"id": "ORD002",
"клиент": "Мария",
"товары": [
{"название": "Ноутбук", "цена": 75000, "количество": 1}
],
"статус": "обработка"
}
]
}
Запросы:
// Все товары во всех заказах
$..товары[]
// Доставленные заказы
$.заказы[?(@.статус == 'доставлен')]
// Заказы с товарами дороже 1000
$.заказы[?(@.товары[].цена > 1000)]
// Все цены товаров
$..товары[].цена
Оптимизация запросов
Специфичность запросов
✅ Эффективно:
$.магазин.книги[*].название
❌ Неэффективно:
$..название // Ищет по всему документу
Кэширование результатов
// Плохо - повторный парсинг
for (let i = 0; i < 1000; i++) {
const результат = jsonpath.query(большиеДанные, сложныйЗапрос);
}
// Хорошо - один раз запрос
const результат = jsonpath.query(большиеДанные, сложныйЗапрос);
for (let i = 0; i < 1000; i++) {
// Использовать результат
}
Ограничения JSONPath
Заключение
JSONPath - мощный инструмент для работы со сложными JSON структурами. Он предоставляет элегантный способ запроса и извлечения данных без написания сложного кода.
Ключевые выводы:
- JSONPath похож на XPath для XML
- Поддерживает фильтры, wildcard и рекурсивный поиск
- Доступен для JavaScript, Python, PHP и других языков
- Идеален для динамических запросов к JSON
- Онлайн инструменты помогают в обучении и отладке
Освоив JSONPath, вы сможете эффективно работать с любыми JSON данными, независимо от их сложности!
Похожие статьи
Лучшие инструменты JSON онлайн в 2026 году
Подробный обзор лучших онлайн инструментов для работы с JSON: валидаторы, форматеры, редакторы и конвертеры.
Работа с большими файлами JSON: Оптимизация и производительность
Эффективные методы обработки больших JSON файлов: streaming, chunking, оптимизация памяти и производительности.
Продвинутые структуры JSON: Паттерны и лучшие практики
Глубокое погружение в сложные JSON структуры: nested objects, circular references, polymorphism, и продвинутые паттерны проектирования.