管道表达式

JEP

4

作者

道林

状态

认可的

创建

2013年12月7日

摘要

本文档建议在后续表达式中添加对管道表达式的支持。

动机

当前的JMESPath语法允许在表达式中的不同点进行投影。但是,目前还无法将投影结果作为列表进行操作。

下面的例子说明了不可能对投影的结果进行操作(例如,获取投影的第一个匹配)。

鉴于:

{
    "foo": {
        "a": {
            "bar": [1, 2, 3]
        },
        "b": {
            "bar": [4, 5, 6]
        }
    }
}

表达式:

foo.*.bar[0]

结果将是每个元素的0 bar

[1, 4]

通过添加过滤器,我们可以将一个表达式的结果传递给另一个表达式,对投影(或任何表达式)的结果进行操作。

表达式:

foo.*.bar | [0]

结果:

[1, 2, 3]

这不仅使我们能够对投影结果进行操作,而且管道表达式还可以用于将复杂表达式分解为更小、更易于理解的部分。

修正语法

以下修改后的JMESPath语法支持管道表达式。

expression        = sub-expression / index-expression / or-expression / identifier / "*"
expression        =/ multi-select-list / multi-select-hash / pipe-expression
sub-expression    = expression "." expression
pipe-expression   = expression "|" expression
or-expression     = expression "||" expression
index-expression  = expression bracket-specifier / bracket-specifier
multi-select-list = "[" ( expression *( "," expression ) ) "]"
multi-select-hash = "{" ( keyval-expr *( "," keyval-expr ) ) "}"
keyval-expr       = identifier ":" expression
bracket-specifier = "[" (number / "*") "]" / "[]"
number            = [-]1*digit
digit             = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "0"
identifier        = 1*char
identifier        =/ quote 1*(unescaped-char / escaped-quote) quote
escaped-quote     = escape quote
unescaped-char    = %x30-10FFFF
escape            = %x5C   ; Back slash: \
quote             = %x22   ; Double quote: '"'
char              = %x30-39 / ; 0-9
                    %x41-5A / ; A-Z
                    %x5F /    ; _
                    %x61-7A / ; a-z
                    %x7F-10FFFF

注解

pipe-expression has a higher precendent than the or-operator

符合性测试

[{
  "given": {
    "foo": {
      "bar": {
        "baz": "one"
      },
      "other": {
        "baz": "two"
      },
      "other2": {
        "baz": "three"
      },
      "other3": {
        "notbaz": ["a", "b", "c"]
      },
      "other4": {
        "notbaz": ["d", "e", "f"]
      }
    }
  },
  "cases": [
    {
      "expression": "foo.*.baz | [0]",
      "result": "one"
    },
    {
      "expression": "foo.*.baz | [1]",
      "result": "two"
    },
    {
      "expression": "foo.*.baz | [2]",
      "result": "three"
    },
    {
      "expression": "foo.bar.* | [0]",
      "result": "one"
    },
    {
      "expression": "foo.*.notbaz | [*]",
      "result": [["a", "b", "c"], ["d", "e", "f"]]
    },
    {
      "expression": "foo | bar",
      "result": {"baz": "one"}
    },
    {
      "expression": "foo | bar | baz",
      "result": "one"
    },
    {
      "expression": "foo|bar| baz",
      "result": "one"
    },
    {
      "expression": "not_there | [0]",
      "result": null
    },
    {
      "expression": "not_there | [0]",
      "result": null
    },
    {
      "expression": "[foo.bar, foo.other] | [0]",
      "result": {"baz": "one"}
    },
    {
      "expression": "{\"a\": foo.bar, \"b\": foo.other} | a",
      "result": {"baz": "one"}
    },
    {
      "expression": "{\"a\": foo.bar, \"b\": foo.other} | b",
      "result": {"baz": "two"}
    },
    {
      "expression": "{\"a\": foo.bar, \"b\": foo.other} | *.baz",
      "result": ["one", "two"]
    },
    {
      "expression": "foo.bam || foo.bar | baz",
      "result": "one"
    },
    {
      "expression": "foo | not_there || bar",
      "result": {"baz": "one"}
    }
  ]
}]

目录