改进的标识符¶
- JEP
6
- 作者
詹姆斯·萨耶维尼
- 状态
认可的
- 创建
2013年12月14日
- 最后更新
2013年12月15日
摘要¶
这个JEP建议对JMESPath进行语法修改,以改进JMESPath中使用的标识符。在这样做时,标识符语法规则中的几个不一致之处将得到修复,同时还有一种改进的语法,用于以与JSON字符串一致的方式指定unicode标识符。
动机¶
目前有两种方法可以指定标识符,即不带引号的规则:
identifier = 1*char
引用的规则是:
identifier =/ quote 1*(unescaped-char / escaped-quote) quote
这个 char
规则包含一组字符 not 必须引用:
char = %x30-39 / ; 0-9
%x41-5A / ; A-Z
%x5F / ; _
%x61-7A / ; a-z
%x7F-10FFFF
在 %x30-39
规则和 number
规则:
number = ["-"]1*digit
digit = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "0"
使用哪条规则还不明确。给定一个字符串“123”,不清楚这是应该被解析为标识符还是数字。现有实现 不是 遵循这个规则(因为它是不明确的),所以应该更新语法以消除歧义,特别是,未加引号的标识符只能以字符开头 [a-zA-Z_]
.
统一码¶
JMESPath通过 char
和 unescaped-char
规则:
unescaped-char = %x30-10FFFF
char = %x30-39 / ; 0-9
%x41-5A / ; A-Z
%x5F / ; _
%x61-7A / ; a-z
%x7F-10FFFF
但是,JSON支持转义unicode字符的语法。基本多语言平面(BMP)中的任何字符都可以用以下方式转义:
char = escape (%x75 4HEXDIG ) ; \uXXXX
类似于XPath支持XML中使用的数字字符引用的方式 (&#nnnn
),JMESPath应支持JSON中使用的相同转义序列。JSON还通过对UTF-16代理项对进行编码,为BMP之外的字符提供12个字符的转义序列。例如,代码点 U+1D11E
可以表示为 "\uD834\uDD1E"
.
转义序列¶
考虑以下JSON对象:
{"foo\nbar": "baz"}
JMESPath表达式应该能够检索baz的值。对于当前的语法,必须依赖于环境输入控制字符(如换行符)的能力 (%x0A
). 这在某些环境中可能会出现问题。例如,在python中,这不是一个问题:
>>> jmespath_expression = "foo\nbar"
Python will interpret the sequence "\n"
(%x5C %x6E
) as the newline
character %x0A
. However, consider Bash:
$ foo --jmespath-expression "foo\nbar"
In this situation, bash will not interpret the "\n"
(%x5C %x6E
)
sequence.
规范¶
这个 char
规则包含一组字符 not 必须被引用。不需要引用的新字符集将是:
unquoted-string = (%x41-5A / %x61-7A / %x5F) *(%x30-39 / %x41-5A / %x5F / %x61-7A)
为了使标识符不被引用,它必须以 [A-Za-z_]
,则后面必须跟零或更多 [0-9A-Za-z_]
.
未加引号的规则已更新,以说明所有JSON支持的转义序列:
quoted-string =/ quote 1*(unescaped-char / escaped-char) quote
标识符的完整规则是:
identifier = unquoted-string / quoted-string
unquoted-string = (%x41-5A / %x61-7A / %x5F) *( ; a-zA-Z_
%x30-39 / ; 0-9
%x41-5A / ; A-Z
%x5F / ; _
%x61-7A) ; a-z
quoted-string = quote 1*(unescaped-char / escaped-char) quote
unescaped-char = %x20-21 / %x23-5B / %x5D-10FFFF
escape = %x5C ; Back slash: \
quote = %x22 ; Double quote: '"'
escaped-char = escape (
%x22 / ; " quotation mark U+0022
%x5C / ; \ reverse solidus U+005C
%x2F / ; / solidus U+002F
%x62 / ; b backspace U+0008
%x66 / ; f form feed U+000C
%x6E / ; n line feed U+000A
%x72 / ; r carriage return U+000D
%x74 / ; t tab U+0009
%x75 4HEXDIG ) ; uXXXX U+XXXX
理论基础¶
采用与JSON字符串相同的字符串规则将允许熟悉JSON语义的用户了解JMESPath标识符的工作方式。
这个变化也为jep3中提出的文本语法提供了很好的一致性。使用此模型,支持的文本字符串可以与带引号的标识符相同。
如果JMESPath添加了对基于文本值的过滤的支持,这也将允许语法以一致的方式增长。例如(请注意,这只是一个建议的语法,而不是一个正式的建议),给定的数据是:
{"foo": [{"✓": "✓"}, {"✓": "✗"}]}
现在可以使用以下JMESPath表达式::
foo[?"✓" = `✓`]
foo[?"\u2713" = `\u2713`]
作为常规属性,任何受支持的JSON字符串现在都是受支持的带引号的标识符。
影响¶
对于任何将数字解析为标识符的实现,以数字开头的标识符将不再有效,例如。 foo.0.1.2
.
有几个符合性测试,将必须更新作为这个JEP的结果。他们可以说一开始就错了。
basic.json¶
由于现在必须引用以数字开头的标识符,因此需要更改以下内容:
- "expression": "foo.1",
+ "expression": "foo.\"1\"",
"result": ["one", "two", "three"]
},
{
- "expression": "foo.1[0]",
+ "expression": "foo.\"1\"[0]",
"result": "one"
},
同样,需要更改以下内容,因为未加引号的标识符不能以 -
::
- "expression": "foo.-1",
+ "expression": "foo.\"-1\"",
"result": "bar"
}
escape.json¶
这个escape.json还有几个中间案件需要更新。这与更新的转义规则有关。每一个都会被解释。
- "expression": "\"foo\nbar\"",
+ "expression": "\"foo\\nbar\"",
"result": "newline"
},
This has to be updated because a JSON parser will interpret the \n
sequence
as the newline character. The newline character is not allowed in a
JMESPath identifier (note that the newline character %0A
is not in any
rule). In order for a JSON parser to create a sequence of %x5C %x6E
, the
JSON string must be \\n
(%x5C %x5C %x6E
).
- "expression": "\"c:\\\\windows\\path\"",
+ "expression": "\"c:\\\\\\\\windows\\\\path\"",
"result": "windows"
},
上面的例子是一个更病态的逃跑案例。在这个例子中,我们有一个代表windows路径“c:\windowpath”的字符串。这里有两个级别的转义,一个在JSON解析器,一个在JMESPath解析器。JSON解析器将获取序列 "\"c:\\\\\\\\windows\\\\path\""
然后创建字符串 "\"c:\\\\windows\\path\""
. JMESPath解析器将接受字符串 "\"c:\\\\windows\\path\"'
并且,应用它自己的转义规则,将查找名为 c:\\windows\path
.