4 JSONPath 功能

概述

本节概述了监控项值预处理步骤中支持的 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() 返回名称为“Object”的第一个对象中 price 属性的值。
$[?(@.name == 'Object')].history.first().length() 返回名称为“Object”的第一个对象中 history 数组元素的数量。
$[?(@.price > 10)].length() 返回价格大于 10 的对象数量。

另请参见:在 JSONPath 中转义 LLD 宏值中的特殊字符

支持的段

描述
<name> 按名称匹配对象属性。
* 匹配所有对象属性。
['<name>'] 按名称匹配对象属性。
['<name>', '<name>', ...] 按列出的任意名称匹配对象属性。
[<index>] 按索引匹配数组元素。
[<number>, <number>, ...] 按列出的任意索引匹配数组元素。
[*] 匹配所有对象属性或数组元素。
[<start>:<end>] 按定义的范围匹配数组元素:
<start> - 要匹配的第一个索引(包含);如果未指定,则匹配从开头开始的所有数组元素;如果为负数,则表示从数组末尾开始的起始偏移量;
<end> - 要匹配的最后一个索引(不包含);如果未指定,则匹配直到末尾的所有数组元素;如果为负数,则表示从数组末尾开始的起始偏移量。
[?(<expression>)] 通过应用过滤表达式匹配对象/数组元素。

要在忽略其祖先的情况下查找匹配的段(分离段),必须在其前面加上两个点(..)。 例如,$..name$..['name'] 会返回所有 name 属性的值。

可以通过在 JSONPath 后添加波浪号(~)后缀来提取匹配元素的名称。 它会返回匹配对象的名称,或匹配数组项的字符串格式索引。 输出格式遵循与其他 JSONPath 查询相同的规则——确定路径的结果按原样返回,而不确定路径的结果则以数组形式返回。 不过,提取匹配确定路径的元素名称意义不大,因为该名称本身已经是已知的。

过滤表达式

过滤表达式是一个中缀表示法中的算术表达式。

支持的操作数:

操作数 描述
"<text>"
'<text>'
文本常量。

示例:
'value: \\'1\\''
"value: '1'"
<number> 支持科学计数法的数值常量。

示例: 123
<jsonpath starting with $> 从输入文档根节点引用的 JSONPath 所指的值;仅支持确定的路径。

示例: $.object.name
<jsonpath starting with @> 从当前对象/元素引用的 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 聚合函数接受带引号的数值。 当需要聚合时,这些值会自动从字符串转换为数值类型。 不兼容的输入将导致函数生成错误。

输出值

JSONPath 可以分为确定路径和不确定路径。 确定路径只能返回 null 或单个匹配项。 不确定路径可以返回多个匹配项:具有分离的、多个名称/索引列表、数组切片或表达式段的 JSONPath。 但是,当使用函数时,JSONPath 变为确定,因为函数始终输出单个值。

确定路径返回它引用的对象/数组/值。 相反,不确定路径返回匹配对象/数组/值的数组。

由于内部优化方法的原因,JSONPath 查询结果中的属性顺序可能与原始 JSON 属性顺序不一致。 例如,JSONPath $.books[1]["author", "title"] 可能返回 ["title", "author"]。 如果保留原始属性顺序很重要,则应考虑使用替代的查询后处理方法。

路径格式化规则

在方括号表示法的段和表达式中可以使用空格(空格、制表符),例如:$[ '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": "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 Type Result
$.filters.price definite 10
$.filters.category definite fiction
$.filters['no filters'] definite no "filters"
$.filters definite {
"price": 10,
"category": "fiction",
"no filters": "no \"filters\""
}
$.books[1].title definite Sword of Honour
$.books[-1].author definite J. R. R. Tolkien
$.books.length() definite 4
$.tags[:] indefinite ["a", "b", "c", "d", "e" ]
$.tags[2:] indefinite ["c", "d", "e" ]
$.tags[:3] indefinite ["a", "b", "c"]
$.tags[1:4] indefinite ["b", "c", "d"]
$.tags[-2:] indefinite ["d", "e"]
$.tags[:-3] indefinite ["a", "b"]
$.tags[:-3].length() definite 2
$.books[0, 2].title indefinite ["Moby Dick", "Sayings of the Century"]
$.books[1]['author', "title"] indefinite ["Sword of Honour", "Evelyn Waugh"]
$..id indefinite [1, 2, 3, 4]
$.services..price indefinite [154.99, 5, 46, 24.5, 99.49]
$.books[?(@.id == 4 - 0.4 * 5)].title indefinite ["Sword of Honour"]

Note: This query shows that arithmetical operations can be used in queries; it can be simplified to $.books[?(@.id == 2)].title
$.books[?(@.id == 2 \|\| @.id == 4)].title indefinite ["Sword of Honour", "The Lord of the Rings"]
$.books[?(!(@.id == 2))].title indefinite ["Sayings of the Century", "Moby Dick", "The Lord of the Rings"]
$.books[?(@.id != 2)].title indefinite ["Sayings of the Century", "Moby Dick", "The Lord of the Rings"]
$.books[?(@.title =~ " of ")].title indefinite ["Sayings of the Century", "Sword of Honour", "The Lord of the Rings"]
$.books[?(@.price > 12.99)].title indefinite ["The Lord of the Rings"]
$.books[?(@.author > "Herman Melville")].title indefinite ["Sayings of the Century", "The Lord of the Rings"]
$.books[?(@.price > $.filters.price)].title indefinite ["Sword of Honour", "The Lord of the Rings"]
$.books[?(@.category == $.filters.category)].title indefinite ["Sword of Honour","Moby Dick","The Lord of the Rings"]
$.books[?(@.category == "fiction" && @.price < 10)].title indefinite ["Moby Dick"]
$..[?(@.id)] indefinite [
{
"price": 8.95,
"id": 1,
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century"
},
{
"price": 12.99,
"id": 2,
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour"
},
{
"price": 8.99,
"id": 3,
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3"
},
{
"price": 22.99,
"id": 4,
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8"
}
]
$.services..[?(@.price > 50)].description indefinite ["Printing and assembling book in A5 format", "Rebinding torn book"]
$..id.length() definite 4
$.books[?(@.id == 2)].title.first() definite Sword of Honour
$..tags.first().length() definite 5

Note: $..tags is an indefinite path, so it returns an array of matched elements, i.e., [["a", "b", "c", "d", "e" ]]; first() returns the first element, i.e., ["a", "b", "c", "d", "e"]; length() calculates the length of the element, i.e.,5.
$.books[*].price.min() definite 8.95
$..price.max() definite 154.99
$.books[?(@.category == "fiction")].price.avg() definite 14.99
$.books[?(@.category == $.filters.xyz)].title indefinite Note: A query without match returns NULL for definite and indefinite paths.
$.services[?(@.active=="true")].servicegroup indefinite [1001,1000]

Note: Text constants must be used in boolean value comparisons.
$.services[?(@.active=="false")].servicegroup indefinite [1002]

Note: Text constants must be used in boolean value comparisons.
$.services[?(@.servicegroup=="1002")]~.first() definite restoration