[comment]: # ({16d8a00a-16d8a00a})
# 3 JSONPath 功能

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

[comment]: # ({a806c032-a806c032})
#### 概述

本节详细说明监控项值预处理步骤中支持的JSONPath功能。

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 array元素的数量。 |
| `$[?(@.name == 'Object')].price.first()` | 返回名称为'object'的第一个object的price字段。 |
| `$[?(@.name == 'Object')].history.first().length()` | 返回名称为'object'的第一个object的history array元素数量。 |
| `$[?(@.price > 10)].length()` | 返回price大于10的objects数量。 |

另请参阅：[Escaping special characters from LLD macro values in
JSONPath](/manual/config/items/preprocessing/jsonpath_functionality/escaping_lld_macros)。

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

[comment]: # ({7b7e8459-74fc1571})
#### 支持的片段

| 片段 | 描述 |
|--|--------|
| `<name>` | 按名称匹配object属性。 |
| `*` | 匹配所有object属性。 |
| `['<name>']` | 按名称匹配object属性。 |
| `['<name>', '<name>', ...]` | 按列出的任意名称匹配object属性。 |
| `[<index>]` | 按索引匹配array元素。 |
| `[<number>, <number>, ...]` | 按列出的任意索引匹配array元素。 |
| `[*]` | 匹配所有object属性或array元素。 |
| `[<start>:<end>]` | 按定义范围匹配array元素：<br>**<起始>** - 要匹配的第一个索引（包含）。如果未指定，则从开头匹配所有array元素。如果为负值，则指定从array末尾的起始偏移量。<br>**<结束>** - 要匹配的最后一个索引（不包含）。如果未指定，则匹配到末尾的所有array元素。如果为负值，则指定从array末尾的起始偏移量。 |
| `[?(<expression>)]` | 通过应用过滤表达式匹配objects/array元素。 |

要忽略祖先关系（分离片段）查找匹配片段，
必须以'..'为前缀，例如`$..name`或`$..['name']`
返回所有'名称'属性的值。

可以通过在JSONPath后添加`~`后缀来提取匹配的元素名称。
它返回匹配的object名称或匹配的array监控项的string格式索引。
输出格式遵循与其他JSONPathqueries相同的规则 - 确定路径结果
按原样返回，不确定路径结果以array形式返回。
然而提取确定路径匹配元素的名称没有太大意义 - 它已经是已知的。

[comment]: # ({/7b7e8459-74fc1571})

[comment]: # ({874df093-5eac028e})
#### 过滤表达式

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

支持的运算数：

| 运算数 | 描述 | 示例 |
|--|------|------|
| `"<text>"`<br>`'<text>'` | 文本常量。 | 'value: \\'1\\''<br>"value: '1'" |
| `<number>` | 支持科学计数法的数字常量。 | 123     |
| `<jsonpath starting with $>` | 从输入文档根节点引用的JSONPath值；仅支持确定路径。 | $.object.name |
| `<jsonpath starting with @>` | 从当前object/元素引用的JSONPath值；仅支持确定路径。 | @.name  |

支持的运算符：

| 运算符 | 类型 | 描述 | 结果 |
|--|--------|----|----|
| `-` | binary | 减法。 | 数字。 |
| `+` | binary | 加法。   | 数字。 |
| `/` | binary | 除法。   | 数字。 |
| `*` | binary | 乘法。 | 数字。 |
| `==` | binary | 等于。 | boolean (1或0)。 |
| `!=` | binary | 不等于。 | boolean (1或0)。 |
| `<` | binary | 小于。 | boolean (1或0)。 |
| `<=` | binary | 小于或等于。 | boolean (1或0)。 |
| `>` | binary | 大于。 | boolean (1或0)。 |
| `>=` | binary | 大于或等于。 | boolean (1或0)。 |
| `=~` | binary | 匹配正则表达式。 | boolean (1或0)。 |
| `!` | unary | boolean 非。 | boolean (1或0)。 |
| `||` | binary | boolean 或。 | boolean (1或0)。 |
| `&&` | binary | boolean 与。 | boolean (1或0)。 |

[comment]: # ({/874df093-5eac028e})

[comment]: # ({acdfaeef-b66eb391})
#### 函数

函数可以用于JSONPath的末尾。如果前一个函数返回的值能被后续函数接受，
则可以链式调用多个函数。

支持的函数：

| 函数 | 描述 | 输入 | 输出 |
|--|--------|----|----|
| `avg` | 输入array中数字的平均值。 | 数字的array。 | 数字。 |
| `min` | 输入array中数字的最小值。 | 数字的array。 | 数字。 |
| `max` | 输入array中数字的最大值。 | 数字的array。 | 数字。 |
| `sum` | 输入array中数字的总和。 | 数字的array。 | 数字。 |
| `length` | 输入array中的元素数量。 | array。 | 数字。 |
| `first` | 第一个array元素。 | array。 | 根据输入array内容返回JSON结构（object、array或值）。 |

JSONPath聚合函数接受带引号的数值。
这意味着如果需要聚合，值会从string类型转换为数字类型。

不兼容的输入将导致函数返回generate错误。

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

[comment]: # ({76f49707-729c09d6})
#### 输出值

JSON路径可分为确定路径和不确定路径。确定路径只能返回null或单一匹配项。不确定路径可返回多个匹配项，主要指包含通配符、多重名称/索引列表、array切片或表达式段的JSON路径。但使用函数时JSON路径会转为确定路径，因为函数始终输出单一值。

确定路径返回其引用的object/array/值，而不确定路径返回匹配objects/数组/值的array集合。

::: noteimportant
由于内部优化方法，JSONPath query结果的属性顺序可能与原始JSON属性顺序不一致。
例如，JSONPath `$.books[1]["author", "title"]`可能返回`["title", "author"]`。
若需保持原始属性顺序，应考虑采用query后处理的替代方案。

:::

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

[comment]: # ({5f0aac44-5f0aac44})
#### 空白字符

在方括号表示法片段和表达式中可以自由使用空白字符（空格、制表符），例如：
`$[ 'a' ][ 0 ][ ?( $.b == 'c' ) ][ : -1 ].first( )`。

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

[comment]: # ({85200782-85200782})
#### 字符串

字符串应使用单引号'或双引号"括起。在字符串内部，单引号或双引号（取决于外围使用的引号类型）以及反斜杠`\`需通过反斜杠`\`字符进行转义。

[comment]: # ({/85200782-85200782})

[comment]: # ({4c860844-4c860844})
#### 示例

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

[comment]: # ({e53fbc59-93072157})
##### 输入数据

```{.java}
{
  "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"
  ]
}
```

| JSON路径 | 类型 | 结果 | 说明 |
|--|--|------|------|
| `$.filters.price` | definite | 10     |          |
| `$.filters.category` | definite | fiction |          |
| `$.filters['no filters']` | definite | no "filters" |          |
| `$.filters` | definite | {<br>"price": 10,<br>"category": "fiction",<br>"no filters": "no \\"filters\\""<br>} |          |
| `$.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"\] | 此query表明算术运算可用于queries。当然这个query可以简化为`$.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 | \[<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` | 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      | $..tags是不定路径，因此返回匹配元素的array - \[\["a", "b", "c", "d", "e" \]\], first()返回第一个元素 - \["a", "b", "c", "d", "e" \]，最后length()计算其长度 - 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 |        | 无匹配的query对于确定和不确定路径返回NULL。 |
| `$.services[?(@.active=="true")].servicegroup` | indefinite | \[1001,1000\] | 文本常量必须用于boolean值比较。 |
| `$.services[?(@.active=="false")].servicegroup` | indefinite | \[1002\] | 文本常量必须用于boolean值比较。 |
| `$.services[?(@.servicegroup=="1002")]~.first()` | definite | restoration |          |

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