JMESPath教程

这是JMESPath语言的教程。JMESPath是一种JSON查询语言。您可以从JSON文档中提取和转换元素。下面的例子是交互式的。您可以更改JMESPath表达式并看到结果自动更新。

对于这些示例中的每一个,JMESPath表达式都应用于左侧的输入JSON,计算JMESPath表达式的结果显示在右侧的JSON文档中。

基本表达式

最简单的JMESPath表达式是 identifier ,它选择JSON对象中的键:

Result

        

尝试将上面的表达式更改为 bc 注意更新的结果。还请注意,如果引用的键不存在,则值 null (或相当于 null )返回。

你可以使用 subexpression 要返回JSON对象中的嵌套值,请执行以下操作:

Result

        

如果引用的键不存在,则值为 null 返回。尝试随后访问标识符将继续返回值 null . 尝试将表达式更改为 b.c.d.e 上面。

Index Expressions 允许您选择列表中的特定元素。它应该类似于通用编程语言中的数组访问。索引基于0。

Result

        

如果指定的索引大于列表,则值为 null 返回。您也可以使用负索引从列表末尾开始索引。 [-1] 引用列表中的最后一个元素, [-2] 引用倒数第二个元素。在上面的例子中尝试一下。

您可以组合标识符、子表达式和索引表达式来访问JSON元素。

Result

        

切片

切片允许您选择数组的连续子集。如果您曾经在python中使用过切片,那么您已经知道如何使用JMESPath切片。在最简单的形式中,可以指定起始索引和结束索引。结束索引是您所做的第一个索引 not 希望包括在切片中。让我们看看一些例子。首先,给定一个0到9的整数数组,让我们选择数组的前半部分:

Result

        

此切片结果包含元素0、1、2、3和4。不包括索引5处的元素。如果要选择数组的后半部分,可以使用以下表达式:

Result

        

上面的两个例子可以缩短。如果 startstep 值被省略,它被假定为数组的开始或结束。例如:

Result

        

尝试修改上面的示例,使其仅包含数组元素的后半部分,而不指定 10 .

切片的一般形式是 [start:stop:step] . 到目前为止,我们已经了解了 [start:stop] 形式。默认情况下 step 价值是 1 ,这意味着包含 startstop 价值观。但是,我们可以使用step值跳过元素。例如,只从数组中选择偶数元素。

Result

        

还要注意在这个例子中我们省略了 start 以及 stop 值,即使用 0 对于 start 价值,以及 10 对于 stop 价值观。在本例中,表达式 [::2] 等于 [0:10:2] .

关于切片的最后一件事是,就像索引单个值一样,所有值都可以是负数。如果 step 值为负,则按相反的顺序创建切片。例如:

Result

        

上面的表达式以相反的顺序创建一个切片。

如果您想了解切片如何工作的所有详细信息,请查看 section in the JMESPath specification .

预测

投影是JMESPath的关键特性之一。它允许您将表达式应用于元素集合。有五种投影:

  • 列出投影

  • 切片投影

  • 物体投影

  • 展平投影

  • 过滤投影

列表和切片投影

A wildcard expression 创建一个列表投影,它是一个JSON数组上的投影。这最好用一个例子来说明。假设我们有一个描述一个人的JSON文档,每个数组元素都是一个JSON对象,它有一个 firstlastage 钥匙。假设我们想要一份名单上所有的名字。

Result

        

在上面的示例中, first 表达式(它只是一个标识符)应用于 people 数组。结果被收集到一个JSON数组中,并作为表达式的结果返回。表达式可以比基本表达式更复杂 identifier .例如,表达式 foo[*].bar.baz[0] 会投射出 bar.baz[0] 中每个元素的表达式 foo 数组。

在使用投影时,有几点要记住。这些将在 wildcard expressions 一节,但要点是:

  • 预测评估分为两个步骤。左侧(LHS)创建一个初始值的JSON数组。投影的右侧(RHS)是要为左侧创建的JSON数组中的每个元素投影的表达式。在计算左手侧和/或右手侧时,每种投影类型的语义略有不同。

  • 如果表达式投影到单个数组元素上的结果是 null ,则从收集的结果集中忽略该值。

  • 可以使用管道表达式停止投影(稍后讨论)。

  • 列表投影仅对JSON数组有效。如果值不是列表,则表达式的结果是 null .

你可以在上面的演示中试试这个。注意如何 people[*].first 只包含三个元素,尽管人员数组有四个元素。这是因为最后一个元素, {{"missing": "different"}} 评估到 null 当表达式 first 已应用,并且 null 值不会添加到收集的结果数组中。如果你试试这个表达式 foo[*].bar 您将看到 null ,因为与 foo key是一个JSON对象,而不是一个数组,列表投影只为JSON数组定义。

切片投影与列表投影几乎相同,只是左侧是对切片求值的结果,它可能不包括原始列表中的所有元素:

Result

        

物体投影

列表投影是为JSON数组定义的,而对象投影是为JSON对象定义的。可以使用创建对象投影 * 语法。这将创建JSON对象的值列表,并将投影的右侧投影到值列表上。

Result

        

在上面的示例中, * 创建一个JSON数组,该数组包含和 ops JSON对象。投影的右侧, numArgs ,然后应用于JSON数组,从而得到 [2, 3] . 下面是一个示例演练,演示了一个实现如何 潜在地 实现对对象投影的求值。首先,物体投影可以分解为两个部分,左手边(LHS)和右手边(RHS):

  • LHSops

  • RHSnumArgs

首先,评估LHS以创建要投影的初始阵列:

evaluate(ops, inputData) -> [{"numArgs": 2}, {"numArgs": 3},
                             {"variadic": True}]

然后将RHS应用于数组中的每个元素:

evaluate(numArgs, {numArgs: 2}) -> 2
evaluate(numArgs, {numArgs: 3}) -> 3
evaluate(numArgs, {variadic: true}) -> null

任何 null 值不包括在最终结果中,因此整个表达式的结果是 [2, 3] .

展平投影

JMESPath表达式中可以使用多个投影。对于列表/对象投影,在投影中创建投影时,原始文档的结构将保留。例如,让我们来看看表达式 reservations[*].instances[*].state . 此表达式表示顶级键 reservations 以数组作为值。对于每个数组元素,投射 instances[*].state 表达式。在每个列表元素中,都有一个 instances 键本身就是一个值,我们为列表中的每个列表元素创建一个子投影。下面是一个例子:

Result

        

这个表达式的结果是 [["running", "stopped"], ["terminated", "running"]] ,这是一个列表列表。外部列表来自 reservations[*] ,而内部列表是 state 创建自 instances[*] ::

1st       r0                         r1
2nd i0          i1             i0            i1
[["running", "stopped"], ["terminated", "running"]]

如果我们只需要实例的所有状态的列表呢?我们最理想的结果是 ["running", "stopped", "terminated", "running"] . 在这种情况下,我们不关心实例属于哪个保留,我们只需要一个状态列表。

这是一个问题 Flatten Projection 解决方案。要获得所需的结果,可以使用 [] 而不是 [*] 要展开列表: reservations[].instances[].state . 试着换衣服 [*][] 在上面的表达式中查看结果是如何变化的。

spec 更详细地说,这是一个简单的经验法则,用于“展平”操作符, [] ,是不是:

  • 它将子列表展平到父列表中(不是递归的,只是一个级别)。

  • 它将创建一个投影,因此展平投影RHS上的任何内容都将投影到新创建的展平列表上。

你也可以用 [] 单凭一己之力就可以把名单压平:

Result

        

如果你再把表达式的结果展平, [][] ,你会得到一个结果 [0, 1, 2, 3, 4, 5, 6, 7] . 在上面的例子中尝试一下。

过滤投影

到目前为止,我们已经看到:

  • 列表/切片投影

  • 物体投影

  • 展平投影

计算投影的RHS是滤波器的一种基本类型。如果针对单个元素计算的表达式结果导致 null ,则从最终结果中排除元素。

过滤投影允许您过滤投影的左侧 之前 计算投影的RHS。

例如,假设我们有一个机器列表,每个机器都有一个 name 和A state . 我们想要所有正在运行的机器的名称。在伪代码中,这将是:

result = []
foreach machine in inputData['machines']
  if machine['state'] == 'running'
    result.insert_at_end(machine['name'])
return result

可以使用过滤器投影来实现这一点:

Result

        

试着换衣服 runningstopped 在上面的例子中。也可以删除 .name 如果您只需要具有指定状态的每台机器的整个JSON对象,则在表达式的末尾。

筛选器表达式是为数组定义的,具有通用形式 LHS [? <expression> <comparator> <expression>] RHS . 这个 filter expression spec详细说明了可用的比较器及其工作原理,但支持标准比较器,即 ==, !=, <, <=, >, >= .

管道表达式

投影是JMESPath中的一个重要概念。但是,有时投影语义 not 你想要什么。一个常见的情况是当您想要操作 结果 而不是将表达式投射到数组中的每个元素上。例如,表达式 people[*].first 将为您提供一个数组,其中包含人员数组中每个人的名字。如果你想要列表中的第一个元素呢?如果你试过了 people[*].first[0] 你刚刚评估的 first[0] 对于people数组中的每个元素,由于没有为字符串定义索引,最终结果将是空数组, [] . 要获得所需的结果,可以使用管道表达式, <expression> | <expression> ,表示投影必须停止。如下例所示:

Result

        

在上面的示例中,列表投影的RHS是 first . 当遇到管道时,到该点的结果将传递给管道表达式的RHS。管道表达式的计算结果为:

evaluate(people[*].first, inputData) -> ["James", "Jacob", "Jayden"]
evaluate([0], ["James", "Jacob", "Jayden"]) -> "James"

MultiSelect

到目前为止,我们已经研究了JMESPath表达式,这些表达式有助于将JSON文档缩减为您感兴趣的元素。下一个概念, multiselect listsmultiselect hashes 允许您创建JSON元素。这允许您创建JSON文档中不存在的元素。multiselect列表创建一个列表,multiselect散列创建一个JSON对象。

这是一个多选择列表的示例:

Result

        

在上面的表达式中 [name, state.name] 部分是一个多选列表。它说要创建一个包含两个元素的列表,第一个元素是 name 表达式,第二个元素是 state.name . 因此,每个list元素将创建一个双元素列表,整个表达式的最终结果是两个元素列表的列表。

与投影不同,表达式的结果始终包含在内,即使结果为空。如果将上述表达式更改为 people[].[foo, bar] 每个两个元素列表 [null, null] .

multiselect具有与multiselect列表相同的基本概念,只是它创建了一个散列而不是数组。使用上面的同一个例子,如果我们想创建一个有两个键的两个元素散列, NameState ,我们可以用这个:

Result

        

功能

JMESPath支持函数表达式,例如:

Result

        

函数可用于以强大的方式转换和过滤数据。可以找到完整的函数列表 herefunction expression 规范有完整的细节。

下面是一些函数的示例。

此示例打印 people 数组:

Result

        

函数也可以与过滤器表达式组合使用。在下面的示例中,JMESPath表达式查找 myarray 包含字符串的 foo .

Result

        

这个 @ 上例中的字符引用正在计算的当前元素 myarray . 表达式 contains(@, `foo`) 将返回 true 如果 myarray 数组包含字符串 foo .

function expression spec提供了所有细节,在使用函数时需要记住以下几点:

  • 函数参数具有类型。如果函数的参数类型错误,则 invalid-type 将发生错误。有些函数可以进行类型转换 (to_stringto_number )以帮助将参数转换为其正确类型。

  • 如果使用错误数量的参数调用函数,则 invalid-arity 将会发生。

下一步

我们现在已经看到了JMESPath语言的概述。接下来要做的是:

  • JMESPath示例 . 您将看到超出教程范围的常见JMESPath表达式。您还将看到如何将多个特性组合在一起,以便最好地利用JMESPath表达式。

  • 要真正开始使用JMESPath,请选择您选择的语言,并查看 JMESPath库 有关在所选语言中使用JMESPath的更多信息,请访问。

  • 阅读 JMESPath Spec ,它有官方的ABNF语法和语言语义的全部细节。