[comment]: # translation:outdated

[comment]: # ({ece5d44c-16d8a00a})
# 4. Поддержка функционала JSONPath

[comment]: # ({/ece5d44c-16d8a00a})

[comment]: # ({aac69794-a806c032})
#### Обзор

В этом разделе описывается поддерживаемый функционал JSONPath в шагах предварительной обработки значений элементов данных.

JSONPath состоит из сегментов, разделенных точками. Сегмент может быть иметь форму либо простого слова, представляющего имя значения JSON, либо подстановочного символа (`*`), либо более замысловатой конструкции, заключённой в квадратные скобки.
Точка перед сегментом скобок необязательна и может быть опущена.

|Пример JSONPath|Описание|
|-----|-----|
|`$.object.name`|Возвращает содержимое object.name.|
|`$.object['name']`|Возвращает содержимое object.name.|
|`$.object.['name']`|Возвращает содержимое object.name.|
|`$["object"]['name']`|Возвращает содержимое object.name.|
|`$.['object'].["name"]`|Возвращает содержимое object.name.|
|`$.object.history.length()`|Возвращает количество элементов массива object.history.|
|`$[?(@.name == 'Object')].price.first()`|Возвращает значение свойства `price` первого объекта по имени «Object».|
|`$[?(@.name == 'Object')].history.first().length()`|Возвращает количество элементов массива history первого объекта с именем «Object».|
|`$[?(@.price > 10)].length()`|Возвращает количество объектов с price больше чем 10.|

Смотрите также: [Экранирование специальных символов из значений LLD макросов в JSONPath](/manual/config/items/preprocessing/jsonpath_functionality/escaping_lld_macros).

[comment]: # ({/aac69794-a806c032})

[comment]: # ({1298c5a2-74fc1571})
#### Поддерживаемые сегменты

|Сегмент|Описание|
|--|--------|
|`<имя>`|Соответствие свойству объекта по имени.|
|`*`|Соответствие всем свойствам объекта.|
|`['<имя>']`|Соответствие свойству объекта по имени.|
|`['<имя>', '<имя>', ...]`|Соответствие свойству объекта по любому из перечисленных имён.|
|`[<индекс>]`|Соответствие элементу массива по его индексу.|
|`[<число>, <число>, ...]`|Соответствие элементу массива по любому из перечисленных индексов.|
|`[*]`|Соответствие всем свойствам объекта или элементам массива.|
|`[<начало>:<конец>]`|Соответствие элементам массива по заданному диапазону:<br>**<начало>** — первый индекс соответствия (включительно). Если не указан, соответствует всем элементам с самого начала. В случае отрицательного значения указывает начальное смещение от конца массива.<br>**<конец>** — последний индекс соответствия (не включая). Если не указан, соответствует всем элементам массива до самого конца. В случае отрицательного значения указывает начальное смещение от конца массива.|
|`[?(<выражение>)]`|Соответствие объектов / элементов массива с применением выражения фильтра.|

Чтобы найти соответствующий сегмент, игнорируя его происхождение (отсоединённый сегмент), его необходимо указывать с префиксом '..', например `$..name` или `$..['name']` вернёт значения всех свойств «name».

Соответствующие имена элементов можно извлечь, добавив суффикс `~` к JSONPath. Он возвращает имя соответствующего объекта или индекс в строковом формате соответствующего элемента массива. Формат вывода следует тем же самым правилам, что и остальные запросы JSONPath — результаты определённого пути возвращаются «как есть», а результаты неопределённого пути возвращаются в виде массива. Однако, нет особого смысла извлекать имя соответствующего элемента определённого пути — оно и так уже известно.

[comment]: # ({/1298c5a2-74fc1571})

[comment]: # ({67ca5f43-5eac028e})
#### Выражение фильтра

Выражение фильтра является арифметическим выражением в инфиксной нотации.

Поддерживаемые операнды:

|Операнд|Описание|
|---|-------|
|`"<текст>"`<br>`'<text>'`|Текстовая константа.<br><br>Пример:<br>`'value: \\'1\\''`<br>`"value: '1'"`|
|`<число>`|Числовая константа, поддерживая научное представление.<br><br>Пример: `123`|
|`<jsonpath начиная с $>`|Значение, указанное в JSONPath, начиная с корневого узла входного документа; поддерживаются только определённые пути.<br><br>Пример: `$.object.name`|
|`<jsonpath начиная с @>`|Значение, указанное в JSONPath, начиная с текущего объекта/элемента; поддерживаются только определённые пути.<br><br>Пример: `@.name`|

Поддерживаемые операторы:

|Оператор|Тип|Описание|Результат|
|--|--------|----|----|
|`-`|бинарный|Вычитание|Число|
|`+`|бинарный|Сложение|Число|
|`/`|бинарный|Деление|Число|
|`*`|бинарный|Умножение|Число|
|`==`|бинарный|Равно|Логический (1 или 0)|
|`!=`|бинарный|Не равно|Логический (1 или 0)|
|`<`|бинарный|Меньше чем|Логический (1 или 0)|
|`<=`|бинарный|Меньше чем или равно|Логический (1 или 0)|
|`>`|бинарный|Больше чем|Логический (1 или 0)|
|`>=`|бинарный|Больше чем или равно|Логический (1 или 0)|
|`=~`|бинарный|Соответствие регулярному выражению|Логический (1 или 0)|
|`!`|унарный|Логическое НЕ|Логический (1 или 0)|
|`||`|бинарный|Логическое ИЛИ|Логический (1 или 0)|
|`&&`|бинарный|Логическое И|Логический (1 или 0)|

[comment]: # ({/67ca5f43-5eac028e})

[comment]: # ({8c75d01d-b66eb391})
#### Функции

Функции можно использовать в конце JSONPath. Несколько функций можно включать в цепочку, если предыдущая функция возвращает значение, которое принимается следующей функцией.

Поддерживаемые функции:

|Функция|Описание|Вход|Выход|
|--|--------|----|----|
|`avg`|Среднее значение из чисел во входящем массиве|Массив чисел|Число|
|`min`|Минимальное значение из чисел во входящем массиве|Массив чисел|Число|
|`max`|Максимальное значение из чисел во входящем массиве|Массив чисел|Число|
|`sum`|Сумма чисел во входящем массиве|Массив чисел|Число|
|`length`|Количество элементов во входящем массиве|Массив|Число|
|`first`|Первый элемент массива|Массив|Конструкция JSON (объект, массив, значение), в зависимости от содержимого входящего массива|

Функциями агрегации JSONPath принимаются числовые значения в кавычках. Это означает, что значения преобразуются из строкового типа в числовой, если требуется агрегирование.

Несовместимые входные данные повлекут ошибку в функции.

[comment]: # ({/8c75d01d-b66eb391})

[comment]: # ({e739c583-729c09d6})
#### Результирующее значение

JSONPath можно разделить на определённые и неопределённые пути.
Определённый путь может вернуть только null или одно совпадение.
Неопределённый путь может вернуть несколько совпадений: JSONPath с отсоединёнными несколькими именами / списком индексов, фрагментами массива или сегментами выражения.
Однако, когда используется функция, JSONPath становится определённым, так как функции всегда имеют одиночное результирующее значение.

Определённый путь возвращает объект/массив/значение, на которое он ссылается.
Напротив, неопределённый путь возвращает массив соответствующих объектов/массивов/значений.

::: noteimportant
Порядок свойств в результатах запроса JSONPath может не соответствовать порядку свойств исходного JSON'а из-за внутренних методов оптимизации.
Например, JSONPath `$.books[1]["author", "title"]` может вернуть `["title", "author"]`.
Если сохранение исходного порядка свойств имеет важное значение, следует рассмотреть альтернативные методы обработки пост-запроса.
:::

[comment]: # ({/e739c583-729c09d6})

[comment]: # ({b5105ad4-5f0aac44})
#### Правила форматирования пути

Пробельные символы (пробелы и символы табуляции) можно свободно использовать в сегментах с представлением в виде квадратных скобок и в выражениях, например: `$[ 'a' ][ 0 ][ ?( $.b == 'c' ) ][ : -1 ].first( )`.

Строки должны быть заключены в одинарные (`'`)  или двойные (`"`)  кавычки. Внутри строк одинарные или двойные кавычки (в зависимости от того, в какие кавычки заключена строка) и обратные косые черты (`\`) экранируются при помощи символа обратной косой черты (`\`).

[comment]: # ({/b5105ad4-5f0aac44})

[comment]: # ({f476ebb9-4c860844})
#### Пример

[comment]: # ({/f476ebb9-4c860844})

[comment]: # ({b5257e6a-93072157})

```json
{
  "books": [
    {
      "category": "reference",
      "author": "Nigel Rees",
      "title": "Sayings of the Century",
      "price": 8.95,
      "id": 1
    },
    {
      "category": "fiction",
      "author": "Evelyn Waugh",
      "title": "Sword of Honour",
      "price": 12.99,
      "id": 2
    },
    {
      "category": "fiction",
      "author": "Herman Melville",
      "title": "Moby Dick",
      "isbn": "0-553-21311-3",
      "price": 8.99,
      "id": 3
    },
    {
      "category": "fiction",
      "author": "J. R. R. Tolkien",
      "title": "The Lord of the Rings",
      "isbn": "0-395-19395-8",
      "price": 22.99,
      "id": 4
    }
  ],
  "services": {
    "delivery": {
      "servicegroup": 1000,
      "description": "Next day delivery in local town",
      "active": true,
      "price": 5
    },
    "bookbinding": {
      "servicegroup": 1001,
      "description": "Printing and assembling book in A5 format",
      "active": true,
      "price": 154.99
    },
    "restoration": {
      "servicegroup": 1002,
      "description": "Various restoration methods",
      "active": false,
      "methods": [
        {
          "description": "Chemical cleaning",
          "price": 46
        },
        {
          "description": "Pressing pages damaged by moisture",
          "price": 24.5
        },
        {
          "description": "Rebinding torn book",
          "price": 99.49
        }
      ]
    }
  },
  "filters": {
    "price": 10,
    "category": "fiction",
    "no filters": "no \"filters\""
  },
  "closed message": "Store is closed",
  "tags": [
    "a",
    "b",
    "c",
    "d",
    "e"
  ]
}
```

|JSONPath|Тип|Результат|
|---|-|------|
|`$.filters.price`|определённый|10|
|`$.filters.category`|определённый|fiction|
|`$.filters['no filters']`|определённый|no "filters"|
|`$.filters`|определённый|{<br>"price": 10,<br>"category": "fiction",<br>"no filters": "no \\"filters\\""<br>}|
|`$.books[1].title`|определённый|Sword of Honour|
|`$.books[-1].author`|определённый|J. R. R. Tolkien|
|`$.books.length()`|определённый|4|
|`$.tags[:]`|неопределённый|\["a", "b", "c", "d", "e" \]|
|`$.tags[2:]`|неопределённый|\["c", "d", "e" \]|
|`$.tags[:3]`|неопределённый|\["a", "b", "c"\]|
|`$.tags[1:4]`|неопределённый|\["b", "c", "d"\]|
|`$.tags[-2:]`|неопределённый|\["d", "e"\]|
|`$.tags[:-3]`|неопределённый|\["a", "b"\]|
|`$.tags[:-3].length()`|определённый|2|
|`$.books[0, 2].title`|неопределённый|\["Moby Dick", "Sayings of the Century"\]|
|`$.books[1]['author', "title"]`|неопределённый|\["Sword of Honour", "Evelyn Waugh"\]|
|`$..id`|неопределённый|\[1, 2, 3, 4\]|
|`$.services..price`|неопределённый|\[154.99, 5, 46, 24.5, 99.49\]|
|`$.books[?(@.id == 4 - 0.4 * 5)].title`|неопределённый|\["Sword of Honour"\]<br><br>Примечание: Этот запрос показывает, что в запросах можно использовать математические операции. Конечно, этот запрос можно упростить до `$.books[?(@.id == 2)].title`|
|`$.books[?(@.id == 2 \|\| @.id == 4)].title`|неопределённый|\["Sword of Honour", "The Lord of the Rings"\]|
|`$.books[?(!(@.id == 2))].title`|неопределённый|\["Sayings of the Century", "Moby Dick", "The Lord of the Rings"\]|
|`$.books[?(@.id != 2)].title`|неопределённый|\["Sayings of the Century", "Moby Dick", "The Lord of the Rings"\]|
|`$.books[?(@.title =~ " of ")].title`|неопределённый|\["Sayings of the Century", "Sword of Honour", "The Lord of the Rings"\]|
|`$.books[?(@.price > 12.99)].title`|неопределённый|\["The Lord of the Rings"\]|
|`$.books[?(@.author > "Herman Melville")].title`|неопределённый|\["Sayings of the Century", "The Lord of the Rings"\]|
|`$.books[?(@.price > $.filters.price)].title`|неопределённый|\["Sword of Honour", "The Lord of the Rings"\]|
|`$.books[?(@.category == $.filters.category)].title`|неопределённый|\["Sword of Honour","Moby Dick","The Lord of the Rings"\]|
|`$.books[?(@.category == "fiction" && @.price < 10)].title`|неопределённый|\["Moby Dick"\]|
|`$..[?(@.id)]`|неопределённый|\[<br>{<br>"price": 8.95,<br>"id": 1,<br>"category": "reference",<br>"author": "Nigel Rees",<br>"title": "Sayings of the Century"<br>},<br>{<br>"price": 12.99,<br>"id": 2,<br>"category": "fiction",<br>"author": "Evelyn Waugh",<br>"title": "Sword of Honour"<br>},<br>{<br>"price": 8.99,<br>"id": 3,<br>"category": "fiction",<br>"author": "Herman Melville",<br>"title": "Moby Dick",<br>"isbn": "0-553-21311-3"<br>},<br>{<br>"price": 22.99,<br>"id": 4,<br>"category": "fiction",<br>"author": "J. R. R. Tolkien",<br>"title": "The Lord of the Rings",<br>"isbn": "0-395-19395-8"<br>}<br>\]|
|`$.services..[?(@.price > 50)].description`|неопределённый|\["Printing and assembling book in A5 format", "Rebinding torn book"\]|
|`$..id.length()`|определённый|4|
|`$.books[?(@.id == 2)].title.first()`|определённый|Sword of Honour|
|`$..tags.first().length()`|определённый|5<br><br>Примечание: `$..tags` неопределённый путь, поэтому он вернёт массив соответствующих элементов, т.е. `[["a", "b", "c", "d", "e" ]]`; `first()` вернёт первый элемент, т.е., `["a", "b", "c", "d", "e"]`; `length()` вычислит его размер, т.е.`5`.|
|`$.books[*].price.min()`|определённый|8.95|
|`$..price.max()`|определённый|154.99|
|`$.books[?(@.category == "fiction")].price.avg()`|определённый|14.99|
|`$.books[?(@.category == $.filters.xyz)].title`|неопределённый|Примечание: Запрос без совпадения вернёт NULL по определённому и неопределённому путям.|
|`$.services[?(@.active=="true")].servicegroup`|неопределённый|\[1001,1000\]<br><br>Примечание: В сравнениях логических значений необходимо использовать текстовые константы.|
|`$.services[?(@.active=="false")].servicegroup`|неопределённый|\[1002\]<br><br>Примечание: В сравнениях логических значений необходимо использовать текстовые константы.|
|`$.services[?(@.servicegroup=="1002")]~.first()`|определённый|restoration|

[comment]: # ({/b5257e6a-93072157})
