
Форк JSONPath с http://goessner.net/articles/JsonPath/
[](https://www.npmjs.com/package/jsonpath-plus)
[](badges/tests-badge.svg)
[](badges/coverage-badge.svg)
[](https://snyk.io/test/github/s3u/JSONPath)
<!--[](LICENSE-MIT.txt)-->
[](badges/licenses-badge.svg)
[](https://github.com/JSONPath-Plus/JSONPath/actions/workflows/node.js.yml)
<small>(см. также [лицензии для dev-зависимостей.](https://raw.githubusercontent.com/s3u/JSONPath/master/badges/licenses-badge-dev.svg?sanitize=true))</small>
# JSONPath Plus
Анализ, преобразование и выборочное извлечение данных из JSON-документов
(и объектов JavaScript).
`jsonpath-plus` расширяет исходную спецификацию, добавляя некоторые
дополнительные операторы и делая явными некоторые поведения, которые
оригинал не описывал.
Попробуйте [демо в браузере](https://jsonpath-plus.github.io/JSONPath/demo/) или
[Runkit (Node)](https://npm.runkit.com/jsonpath-plus).
***Обратите внимание: в настоящее время этот проект не поддерживается активно. Мы
можем принять хорошо документированные PR или некоторые простые обновления, но не
намерены самостоятельно вносить исправления или добавлять новые функции.***
## Возможности
* **Соответствие** исходной спецификации jsonpath
* Удобные **дополнения и уточнения**, отсутствующие в исходной спецификации:
* `^` для получения **родителя** совпадающего элемента
* `~` для получения **имён свойств** совпадающих элементов (в виде массива)
* **Селекторы типов** для получения:
* Базовых типов JSON: `@null()`, `@boolean()`, `@number()`, `@string()`, `@array()`, `@object()`
* `@integer()`
* Составного типа `@scalar()` (который также принимает `undefined` и
неконечные числа при запросах к объектам JavaScript, а также все базовые не-объектные/не-функциональные типы)
* `@other()`, используемого совместно с определяемым пользователем `otherTypeCallback`
* Не-JSON типов, которые тем не менее можно использовать при запросах
к не-JSON объектам JavaScript (`@undefined()`, `@function()`, `@nonFinite()`)
* **Сокращённые селекторы** `@path`/`@parent`/`@property`/`@parentProperty`/`@root` внутри фильтров
* **Экранирование**
* `` ` `` для экранирования оставшейся последовательности
* Синтаксис `@['...']`/`?@['...']` для экранирования специальных символов внутри
имён свойств в фильтрах
* Документирует `$..` (**получение всех родительских компонентов**)
* Форматы экспорта **ESM** и **UMD**
* Помимо запрашиваемых значений, **может возвращать различную метаинформацию**,
включая пути или указатели на значение, а также родительский
объект и имя родительского свойства (чтобы позволить модификацию).
* **Утилиты для преобразования** между путями, массивами и указателями
* Опция для **запрета вычислений**, разрешённых в исходной спецификации, или предоставления
**песочницы** для вычисляемых значений.
* Опция **обратного вызова для обработки результатов** по мере их получения.
## Бенчмаркинг
`jsonpath-plus` стабильно производителен как с большими, так и с малыми наборами данных по сравнению с другими библиотеками json-запросов согласно [json-querying-performance-testing](https://github.com/andykais/json-querying-performance-testing). Вы можете проверить эти результаты, [запустив проект самостоятельно](https://github.com/andykais/json-querying-performance-testing#how-to-run) и добавив больше тестов производительности.
## Установка
```shell
npm install jsonpath-plus
```
## Установка
### Node.js
```js
const {JSONPath} = require('jsonpath-plus');
const result = JSONPath({path: '...', json});
```
### Браузер
Для использования в браузере вы можете напрямую подключить `dist/index-browser-umd.cjs`; никакой магии Browserify не требуется:
```html
<script src="node_modules/jsonpath-plus/dist/index-browser-umd.cjs"></script>
<script>
const result = JSONPath.JSONPath({path: '...', json: {}});
</script>
```
### ESM (современные браузеры)
Вы также можете использовать импорты модулей ES6 (для современных браузеров):
```html
<script type="module">
import {
JSONPath
} from './node_modules/jsonpath-plus/dist/index-browser-esm.js';
const result = JSONPath({path: '...', json: {}});
</script>
```
### ESM (сборщики)
Или, если вы собираете свой JavaScript (например, с помощью Rollup), просто используйте,
учитывая, что [`mainFields`](https://github.com/rollup/plugins/tree/master/packages/node-resolve#mainfields)
должен включать `browser` для сборок под браузер (для Node значение по умолчанию, которое
проверяет `module`, должно подойти):
```js
import {JSONPath} from 'jsonpath-plus';
const result = JSONPath({path: '...', json});
```
## Использование
Полная доступная сигнатура:
```
const result = JSONPath([options,] path, json, callback, otherTypeCallback);
```
Аргументы `path`, `json`, `callback` и `otherTypeCallback`
могут быть альтернативно выражены (вместе с любыми другими из
доступных свойств) в `options`.
Обратите внимание, что `result` будет содержать все найденные элементы (опционально
обёрнутые в массив), тогда как `callback` можно использовать, если вы
хотите выполнить некоторую операцию по мере обнаружения каждого элемента, при этом
функция обратного вызова будет выполняться от 0 до N раз в зависимости
от количества независимых элементов, которые должны быть найдены в результате.
См. документацию ниже для получения дополнительной информации о доступных аргументах `JSONPath`.
См. также [документацию API](https://jsonpath-plus.github.io/JSONPath/docs/ts/).
### Свойства
Свойства, которые могут быть указаны в объекте options или
в методе evaluate (в качестве первого аргумента), включают:
- ***path*** (**обязательно**) - Выражение JSONPath в виде (нормализованной
или ненормализованной) строки или массива
- ***json*** (**обязательно**) - Объект JSON для вычисления (будь то
null, boolean, number, string, object или array).
- ***autostart*** (**по умолчанию: true**) - Если указано `false`,
можно вызвать метод `evaluate` вручную.
- ***flatten*** (**по умолчанию: false**) - Будет ли возвращаемый массив результатов
сведён к одномерному массиву.
- ***resultType*** (**по умолчанию: "value"**) - Может быть регистронезависимой формой
"value", "path", "pointer", "parent" или "parentProperty" для определения
соответственно того, возвращать ли результаты как значения найденных элементов,
как их абсолютные пути, как [JSON Pointers](https://tools.ietf.org/html/rfc6901)
к абсолютным путям, как их родительские объекты или как имя свойства
их родителя. Если установлено значение "all", все эти типы будут возвращены
в объекте с типом в качестве имени ключа.
- ***sandbox*** (**по умолчанию: {}**) - Карта ключ-значение переменных, которые должны быть
доступны для вычислений кода, таких как выражения фильтрации. (Обратите внимание,
что текущий путь и значение также будут доступны этим
выражениям; см. раздел Синтаксис для подробностей.)
- ***wrap*** (**по умолчанию: true**) - Оборачивать ли результаты
в массив. Если `wrap` установлено в `false` и результаты не найдены,
будет возвращено `undefined` (в отличие от пустого массива, когда
`wrap` установлено в true). Если `wrap` установлено в `false` и найден
единственный не-массивный результат, этот результат будет единственным возвращённым элементом
(не внутри массива). Однако массив всё равно будет возвращён, если найдено несколько
результатов. Чтобы избежать неоднозначностей (в случае, когда
необходимо различать результат, который является неудачей,
и результат, который является пустым массивом), рекомендуется переключить
значение по умолчанию на `false`.
- ***eval*** (**по умолчанию: "safe"**) - Метод вычисления скриптов.
`safe`: В браузере будет использоваться минимальный движок скриптов, который не
использует `eval` или `Function` и удовлетворяет Content Security Policy. В NodeJS
это не имеет эффекта и эквивалентно native, так как скрипты там безопасны.
`native`: использует нативные возможности скриптов. т.е. небезопасные `eval` или
`Function` в браузере и `vm.Script` в nodejs. `false`: Отключает вычисление выражений
JavaScript и выбрасывает исключения при попытке использования этих выражений.
`callback [ (code, context) => value]`: Пользовательская реализация, которая вызывается
с `code` и `context` в качестве аргументов для возврата вычисленного значения.
`class`: Класс, который создаётся с `code` в качестве аргумента конструктора, и код
вычисляется путём вызова `runInNewContext` с `context`.
``
- ***ignoreEvalErrors*** (**по умолчанию: false**) - Игнорировать ошибки, возникающие во время
вычисления скрипта.
- ***parent*** (**по умолчанию: null**) - В случае, если запрос может быть
выполнен для возврата корневого узла, это позволяет вернуть родителя этого корневого узла
в результатах.
- ***parentProperty*** (**по умолчанию: null**) - В случае, если запрос
может быть выполнен для возврата корневого узла, это позволяет вернуть `parentProperty`
этого корневого узла в результатах. Это может быть строковое
имя свойства или числовой индекс массива.
- ***callback*** (**по умолчанию: (нет)**) - Если указано, обратный вызов будет
вызван немедленно при получении значения конечной точки. Три передаваемых аргумента
будут значением полезной нагрузки (в соответствии с `resultType`),
типом полезной нагрузки (является ли это обычным "value" или "property"
именем) и полным объектом полезной нагрузки (со всеми `resultType`).
- ***otherTypeCallback*** (**по умолчанию: \<Функция, которая выбрасывает ошибку**
**при обнаружении @other()\>**) - В текущем отсутствии поддержки JSON
Schema можно определять типы за пределами встроенных типов, добавив
оператор `@other()` в конец запроса. Если такой
путь встречается, будет вызван `otherTypeCallback` со
значением элемента, его путём, его родителем и именем свойства его родителя,
и он должен вернуть булево значение, указывающее, принадлежит ли предоставленное значение
к типу "other" или нет (или он может обрабатывать преобразования и
возвращать false).
- ***customTypes*** (**по умолчанию: {}**) - Карта ключ-значение имён типов и функций.
Это позволяет создавать пользовательские операторы типов, которые можно использовать в запросах
(например, `@myType()`). Функция будет вызвана со значением элемента,
его путём, его родителем и именем свойства его родителя. Она должна вернуть
булево значение, указывающее, соответствует ли предоставленное значение пользовательскому типу. Также
может быть установлено в:
1. Значение импорта `jsonpath-plus/src/structuredCloningTypes.js`, который предопределяет следующие типы:
@NaN(), @BigIntObject(), @Date(), @Set(), @Map(), @RegExp(),
@Blob(optionalMimeType), @File(optionalMimeType), @Boolean(), @Number(),
@String(), @Infinity(), @negativeInfinity(), @negativeZero(),
@DOMException(), @Error(), @EvalError(), @RangeError(), @ReferenceError(),
@SyntaxError(), @TypeError(), @URIError(), @AggregateError(),
@QuotaExceededError(), @WebTransportError(), @FileList, @ArrayBuffer(),
@DataView(), @ImageData(), @ImageBitmap(), @Int8Array(), @Uint8Array(),
@Uint8ClampedArray(), @Int16Array(), @Uint16Array(), @Int32Array(),
@Uint32Array(), @Float32Array(), @Float64Array(), @BigInt64Array(),
@BigUint64Array(), @Float16Array, @DOMMatrix(), @DOMMatrixReadOnly(),
@DOMPoint(), @DOMPointReadOnly(), @DOMRect, @DOMRectReadOnly(),
@DOMQuad(), @CryptoKey(), @AudioData(), @EncodedAudioChunk(),
@EncodedVideoChunk(), @VideoFrame(), @CropTarget,
@FileSystemDirectoryHandle(), @FileSystemFileHandle(),
@GPUCompilationInfo(), @GPUCompilationMessage(),
@GPUPipelineError(), @RTCCertificate(), @RTCEncodedAudioFrame(),
@RTCEncodedVideoFrame()
2. Значение импорта `jsonpath-plus/src/javascriptTypes.js`, который предопределяет следующие типы:
@Generator(), @AsyncGenerator(), @GeneratorFunction(),
@AsyncGeneratorFunction(), @Iterable(), @AsyncIterable(), @Iterator()
### Методы экземпляра
- ***evaluate(path, json, callback, otherTypeCallback)*** ИЛИ
***evaluate({path: \<path\>, json: \<json object\>, callback:***
***\<callback function\>, otherTypeCallback:***
***\<otherTypeCallback function\>})*** - Этот метод необходим
только если свойство `autostart` установлено в `false`. Его
можно использовать для повторных вычислений с использованием одной и той же конфигурации.
Помимо перечисленных свойств, последний шаблон метода может
принимать любые другие разрешённые свойства экземпляра (кроме
`autostart`, который здесь не имел бы значения).
### Свойства и методы класса
- ***JSONPath.clearCache()*** - Очищает внутренний кэш разобранных путей и
скомпилированных скриптов. Содержимое кэша не раскрывается; вызывайте этот метод, когда
необходима инвалидация кэша.
- ***JSONPath.toPathArray(pathAsString)*** - Принимает нормализованный или
ненормализованный путь в виде строки и преобразует в массив: например,
`['$', 'aProperty', 'anotherProperty']`.
- ***JSONPath.toPathString(pathAsArray)*** - Принимает массив пути и
преобразует в нормализованную строку пути. Строка будет в форме
вида: `$['aProperty']['anotherProperty][0]`. Терминальные
конструкции JSONPath `~` и `^` и операторы типов, такие как `@string()`,
молча удаляются.
- ***JSONPath.toPointer(pathAsArray)*** - Принимает массив пути и
преобразует в [JSON Pointer](https://tools.ietf.org/html/rfc6901).
Строка будет в форме вида: `/aProperty/anotherProperty/0`
(с любыми внутренними символами `~` и `/`, экранированными в соответствии со спецификацией JSON
Pointer). Терминальные конструкции JSONPath `~` и `^` и
операторы типов, такие как `@string()`, молча удаляются.
## Синтаксис на примерах
Учитывая следующий JSON, взятый с <http://goessner.net/articles/JsonPath/>:
```json
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
```
и следующее XML-представление:
```xml
<store>
<book>
<category>reference</category>
<author>Nigel Rees</author>
<title>Sayings of the Century</title>
<price>8.95</price>
</book>
<book>
<category>fiction</category>
<author>Evelyn Waugh</author>
<title>Sword of Honour</title>
<price>12.99</price>
</book>
<book>
<category>fiction</category>
<author>Herman Melville</author>
<title>Moby Dick</title>
<isbn>0-553-21311-3</isbn>
<price>8.99</price>
</book>
<book>
<category>fiction</category>
<author>J. R. R. Tolkien</author>
<title>The Lord of the Rings</title>
<isbn>0-395-19395-8</isbn>
<price>22.99</price>
</book>
<bicycle>
<color>red</color>
<price>19.95</price>
</bicycle>
</store>
```
Обратите внимание, что приведённые ниже примеры XPath не различают
извлечение элементов и их текстового содержимого (кроме случаев, когда это
полезно для сравнений или во избежание неоднозначности). Примечание: для проверки примеров XPath
(включая примеры для 2.0) может быть полезно [это демо](http://videlibri.sourceforge.net/cgi-bin/xidelcgi)
(установите `xml` или `xml-strict`).
| XPath | JSONPath | Результат | Примечания |
|-------------------------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `/store/book/author` | `$.store.book[*].author` | Авторы всех книг в магазине | Также может быть представлено без `$.` как `store.book[*].author` (хотя это отсутствует в оригинальной спецификации); обратите внимание, что некоторые символьные литералы (`$` и `@`) требуют экранирования, однако |
| `//author` | `$..author` | Все авторы | |
| `/store/*` | `$.store.*` | Всё в магазине, а именно его книги (массив книг) и красный велосипед (объект велосипеда). | |
| `/store//price` | `$.store..price` | Цена всего в магазине. | |
| `//book[3]` | `$..book[2]` | Третья книга (объект книги) | |
| `//book[last()]` | `$..book[(@.length-1)]` <br> `$..book[-1:]` | Последняя книга по порядку. | Для доступа к свойству со специальным символом используйте `[(@['...'])]` для фильтра (эта конкретная возможность отсутствует в оригинальной спецификации) |
| `//book[position()<3]` | `$..book[0,1]` <br> `$..book[:2]` | Первые две книги | |
---
[Read more](https://github.com/jsonpath-plus/jsonpath)