JEP | 1 |
Author | Michael Dowling |
Status | accepted |
Created | 27-Nov-2013 |
This document proposes modifying the JMESPath grammar
to support arbitrarily nested expressions within multi-select-list
and
multi-select-hash
expressions.
This JMESPath grammar currently does not allow arbitrarily nested expressions
within multi-select-list
and multi-select-hash
expressions. This
prevents nested branching expressions, nested multi-select-list
expressions
within other multi expressions, and nested or-expressions
within any
multi-expression.
By allowing any expression to be nested within a multi-select-list
and
multi-select-hash
expression, we can trim down several grammar rules and
provide customers with a much more flexible expression DSL.
Supporting arbitrarily nested expressions within other expressions requires:
-
Updating the grammar to remove
non-branched-expr
-
Updating compliance tests to add various permutations of the grammar to ensure implementations are compliant.
-
Updating the JMESPath documentation to reflect the ability to arbitrarily nest expressions.
Given:
{
"foo": {
"baz": [
{
"bar": "abc"
}, {
"bar": "def"
}
],
"qux": ["zero"]
}
}
With: foo.[baz[*].bar, qux[0]]
Result:
[
[
"abc",
"def"
],
"zero"
]
Given:
{
"foo": {
"baz": [
{
"bar": "a",
"bam": "b",
"boo": "c"
}, {
"bar": "d",
"bam": "e",
"boo": "f"
}
],
"qux": ["zero"]
}
}
With: foo.[baz[*].[bar, boo], qux[0]]
Result:
[
[
[
"a",
"c"
],
[
"d",
"f"
]
],
"zero"
]
Given:
{
"foo": {
"baz": [
{
"bar": "a",
"bam": "b",
"boo": "c"
}, {
"bar": "d",
"bam": "e",
"boo": "f"
}
],
"qux": ["zero"]
}
}
With: foo.[baz[*].not_there || baz[*].bar, qux[0]]
Result:
[
[
"a",
"d"
],
"zero"
]
Because there are no breaking changes from this modification, existing multi-select expressions will still work unchanged:
Given:
{
"foo": {
"baz": {
"abc": 123,
"bar": 456
}
}
}
With: foo.[baz, baz.bar]
Result:
[
{
"abc": 123,
"bar": 456
},
456
]
The following modified JMESPath grammar supports arbitrarily nested expressions and is specified using ABNF, as described in RFC4234
expression = sub-expression / index-expression / or-expression / identifier / "*"
expression =/ multi-select-list / multi-select-hash
sub-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