13 Поддержка JSONPath функционала

Полная функциональность JSONPath, как описано на этой странице, доступна начиная с Zabbix 4.2.5.

Обзор

JSONPath состоит из сегментов разделенных точками. Сегмент может быть как простым словом, например имя значения JSON, *, так и более сложной конструкцией заключённой в квадратные скобки [ ]. Разделительная точка перед сегментом скобки является опциональной и её можно опустить. Например:

Путь Описание
$.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.

Поддерживаемые сегменты

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

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

Фильтрация выражения

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

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

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

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

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

Функции

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

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

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

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

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

Результирующее значение

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

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

Пробелы

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

Строки

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

Примеры

Входящие данные
{
         "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": "Checmical 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 определённый {
"price": 10,
"category": "fiction",
"no filters": "no \"filters\""
}
$.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 неопределённый ["Sayings of the Century", "Moby Dick"]
$.books[1]['author', "title"] неопределённый ["Evelyn Waugh", "Sword of Honour"]
$..id неопределённый [1, 2, 3, 4]
$.services..price неопределённый [5, 154.99, 46, 24.5, 99.49]
$.books[?(@.id == 4 - 0.4 * 5)].title неопределённый ["Sword of Honour"] Этот запрос показывает, что в запросах можно использовать математические операции. Конечно, этот запрос можно упростить до $.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"]
$..[?(@.id)] неопределённый [
{
"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..[?(@.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 $..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 неопределённый [1000,1001] В сравнениях логических значений необходимо использовать текстовые константы.
$.services[?(@.active=="false")].servicegroup неопределённый [1002] В сравнениях логических значений необходимо использовать текстовые константы.