[comment]: # translation:outdated

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

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

[comment]: # ({d1856c5f-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数组元素的个数。|
|`$[?(@.name == 'Object')].price.first()`|返回第一个名为'Object'的对象的价格字段。|
|`$[?(@.name == 'Object')].history.first().length()`|返回第一个名为'Object'的对象的历史数组元素个数。|
|`$[?(@.price > 10)].length()`|返回price大于10的对象个数。|

参考: [从 JSONPath 中的 LLD 宏值中转义特殊字符](/manual/config/items/preprocessing/jsonpath_functionality/escaping_lld_macros).

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

[comment]: # ({25f79a23-74fc1571})
#### 支持的段

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

要查找忽略其根节点的匹配段（单独的段），它必须以 '..' 为前缀，例如 `$..name` 或 `$..['name']` 返回所有 'name' 属性的值。

可以通过在 JSONPath 中添加 `~` 后缀来提取匹配的元素名称。 它返回匹配对象的名称或匹配数组项的字符串格式的索引。 输出格式遵循与其他 JSONPath 查询相同的规则 - 确定路径结果按“原样”返回，不确定路径结果以数组形式返回。 但是，提取与明确路径匹配的元素的名称并没有多大意义——它是已知的。

[comment]: # ({/25f79a23-74fc1571})

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

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

支持的操作数：

|操作数|描述|
|---|-------|
|`"<text>"`<br>`'<text>'`|文本常量。<br><br>示例：<br>`'value: \\'1\\''`<br>`"value: '1'"`|
|`<number>`|支持科学计数法的数值常量。<br><br>示例： `123`|
|`<jsonpath starting with $>`|从输入文档根节点引用的 JSONPath 所指的值；仅支持确定的路径。<br><br>示例： `$.object.name`|
|`<jsonpath starting with @>`|从当前对象/元素引用的 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]: # ({0ea0784e-b66eb391})
#### 函数

函数可以用在 JSONPath 的末尾。 如果前面的函数返回后面函数接受的值，则可以链接多个函数。

支持的函数：

|函数|描述|输入|输出|
|--------|-----------|-----|------|
|`avg`|输入数组中数字的平均值。|数字数组。|数字。|
|`min`|输入数组中数字的最小值。|数字数组。|数字。|
|`max`|输入数组中数字的最大值。|数字数组。|数字。|
|`sum`|输入数组中数字的总和。|数字数组。|数字。|
|`length`|输入数组中的元素数量。|数组。|数字。|
|`first`|第一个数组元素。|数组。|取决于输入数组内容的 JSON 构造（对象、数组、值）。|

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

不兼容的输入会导致函数产生错误。

[comment]: # ({/0ea0784e-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]: # ({6863fa4f-4c860844})
#### 示例

[comment]: # ({/6863fa4f-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|Type|Result|
|---|-|------|
|`$.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"\]<br><br>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|\[<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<br><br>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\]<br><br>Note: Text constants must be used in boolean value comparisons.|
|`$.services[?(@.active=="false")].servicegroup`|indefinite|\[1002\]<br><br>Note: Text constants must be used in boolean value comparisons.|
|`$.services[?(@.servicegroup=="1002")]~.first()`|definite|restoration|

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