Postgresql 中文操作指南

8.14. JSON Types #

JSON 数据类型用于存储 JSON(JavaScript 对象表示法)数据,如 RFC 7159中所规定。此类数据也可以存储为 text,但 JSON 数据类型的优势在于,它强制要求每个存储的值都根据 JSON 规则有效。还有各种可用于存储在这些数据类型中的数据的 JSON 特定函数和运算符;请参见 Section 9.16

PostgreSQL 提供了两种用于存储 JSON 数据的类型:json_和 _jsonb。为了实现这些数据类型的查询机制,PostgreSQL 还提供了 _jsonpath_数据类型, Section 8.14.7 中对其进行了说明。

jsonjsonb 数据类型接受 almost 相同的输入值集。主要的实际区别在于效率。json 数据类型存储输入文本的精确副本,处理函数在每次执行时都必须重新解析;而 jsonb 数据存储在分解的二进制格式中,由于增加了转换开销,其输入速度略慢,但处理速度明显更快,因为无需重新解析。jsonb 还支持索引,这可能是一个显着的优势。

由于 json 类型存储输入文本的精确副本,因此它将保留标记之间的语义无关空格,以及 JSON 对象中键的顺序。此外,如果值中的 JSON 对象包含相同的键不止一次,则保留所有键/值对。(处理函数将最后一个值视为有效值。)相比之下,jsonb 不保留空格,不保留对象键的顺序,也不保留重复的对象键。如果在输入中指定了重复的键,则只保留最后一个值。

一般而言,除非存在非常特殊的需求(例如对象键排序的旧假设),大多数应用程序都应更喜欢将 JSON 数据存储为 jsonb

RFC 7159 规定 JSON 字符串应编码为 UTF8。因此,如果数据库编码不是 UTF8,则 JSON 类型无法严格符合 JSON 规范。尝试直接包含无法在数据库编码中表示的字符将失败;相反,允许包含可以在数据库编码中表示但不能在 UTF8 中表示的字符。

RFC 7159允许JSON字符串包含由 \u_XXXX_ 表示的Unicode转义序列。在 json 类型的输入函数中,允许Unicode转义,而不管数据库编码如何,而且仅检查其语法正确性(即 \u 后面是否有四个十六进制数字)。但是, jsonb 的输入函数更为严格:它禁止对不能用数据库编码表示的字符进行Unicode转义。 jsonb 类型也拒绝 \u0000 (因为它不能用PostgreSQL的 text 类型表示),并且它坚持正确使用Unicode代理对来指定Unicode基本多语言平面的外部字符。有效的Unicode转义转换为等效的单个字符以进行存储;这包括将代理对折叠成单个字符。

Note

Section 9.16 中描述的许多 JSON 处理函数将把 Unicode 转义转换为常规字符,因此即使它们的输入类型为 json 而不是 jsonb,也仍然会引发刚才描述的同类错误。尽管这允许在不支持已表示字符的数据库编码中简单存储(不做处理)JSON Unicode 转义序列,但 json 输入函数不执行这些检查的事实可被视作一种历史遗留问题。

在将文本 JSON 输入转换为 _jsonb_时,RFC 7159 中描述的基本类型会有效映射到本机 PostgreSQL 类型,如 Table 8.23所示。因此,对于构成有效 _jsonb_数据的额外限制很小,而这些限制不适用于 _json_类型,也不适用于抽象的 JSON,与基础数据类型可以表示的内容限制相对应。值得注意的是,_jsonb_将拒绝超出 PostgreSQL _numeric_数据类型的范围的数字,而 _json_不会。RFC 7159 允许此类实现定义的限制。然而,在实践中,此类问题更有可能发生在其他实现中,因为将 JSON 的 _number_基本类型表示为 IEEE 754 双精度浮点数很常见(RFC 7159 明确预期并允许了这一点)。将 JSON 作为与此类系统互换的格式使用时,应该考虑与 PostgreSQL 最初存储的数据相比丢失数字精度的风险。

相反,如表中所述,对于 JSON 基本类型的输入格式有一些较小的限制,这不适用于相应的 PostgreSQL 类型。

Table 8.23. JSON Primitive Types and Corresponding PostgreSQL Types

JSON primitive type

PostgreSQL type

Notes

string

text

\u0000 被禁止,并且表示数据库编码中不可用字符的Unicode转义也被禁止

number

numeric

禁止 NaNinfinity

boolean

boolean

只接受小写的 truefalse 拼写

null

(none)

SQL NULL 是一个不同的概念

8.14.1. JSON Input and Output Syntax #

JSON 数据类型的输入/输出语法如 RFC 7159 中所指定。

以下是所有有效的 json(或 jsonb)表达式:

-- Simple scalar/primitive value
-- Primitive values can be numbers, quoted strings, true, false, or null
SELECT '5'::json;

-- Array of zero or more elements (elements need not be of same type)
SELECT '[1, 2, "foo", null]'::json;

-- Object containing pairs of keys and values
-- Note that object keys must always be quoted strings
SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json;

-- Arrays and objects can be nested arbitrarily
SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json;

如前所述,当输入一个 JSON 值然后在不进行任何其他处理的情况下打印该值时,json 输出与输入相同的文本,而 jsonb 则不会保留空格等语义无关的详细信息。例如,请注意此处差异:

SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json;
                      json
-------------------------------------------------
 {"bar": "baz", "balance": 7.77, "active":false}
(1 row)

SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
                      jsonb
--------------------------------------------------
 {"bar": "baz", "active": false, "balance": 7.77}
(1 row)

一个值得注意的语义无关细节是,在 jsonb 中,数字将根据底层 numeric 类型的行为进行打印。在实践中,这意味着以 E 符号输入的数字将不带符号打印,例如:

SELECT '{"reading": 1.230e-5}'::json, '{"reading": 1.230e-5}'::jsonb;
         json          |          jsonb
-----------------------+-------------------------
 {"reading": 1.230e-5} | {"reading": 0.00001230}
(1 row)

但是,jsonb 将保留尾随小数零,如本例所示,即使对于相等性检查之类的目的语义上不重要。

有关用于构造和处理 JSON 值的内置函数和运算符列表,请参见 Section 9.16

8.14.2. Designing JSON Documents #

将数据表示为 JSON 可以比传统的关联数据模型更灵活,在需求不断变化的环境中非常吸引人。两种方法完全有可能在同一个应用程序中共存并相互补充。但是,即使对于需要最大灵活性的应用程序,仍然建议 JSON 文档具有固定的结构。该结构通常不强制执行(虽然可以声明性地执行某些业务规则),但具有可预测的结构使编写有用的总结表中的一组“文档”(数据)的查询变得更加容易。

存储在表中的 JSON 数据受与任何其他数据类型相同的并发控制考虑。尽管存储大型文档是可行的,但请记住,任何更新都会获取对整行的行级锁。考虑将 JSON 文档限制为可管理的大小,以减少更新事务之间的锁争用。理想情况下,每个 JSON 文档都应该表示一个原子数据,业务规则规定不能合理地进一步细分为可以独立修改的较小数据。

8.14.3. jsonb Containment and Existence #

测试 containmentjsonb 的一项重要功能。没有针对 json 类型的一组并行设施。包含测试是否一个 jsonb 文档包含在另一个文档中。除了有注释的,这些示例返回 true:

-- Simple scalar/primitive values contain only the identical value:
SELECT '"foo"'::jsonb @> '"foo"'::jsonb;

-- The array on the right side is contained within the one on the left:
SELECT '[1, 2, 3]'::jsonb @> '[1, 3]'::jsonb;

-- Order of array elements is not significant, so this is also true:
SELECT '[1, 2, 3]'::jsonb @> '[3, 1]'::jsonb;

-- Duplicate array elements don't matter either:
SELECT '[1, 2, 3]'::jsonb @> '[1, 2, 2]'::jsonb;

-- The object with a single pair on the right side is contained
-- within the object on the left side:
SELECT '{"product": "PostgreSQL", "version": 9.4, "jsonb": true}'::jsonb @> '{"version": 9.4}'::jsonb;

-- The array on the right side is not considered contained within the
-- array on the left, even though a similar array is nested within it:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[1, 3]'::jsonb;  -- yields false

-- But with a layer of nesting, it is contained:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[[1, 3]]'::jsonb;

-- Similarly, containment is not reported here:
SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"bar": "baz"}'::jsonb;  -- yields false

-- A top-level key and an empty object is contained:
SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"foo": {}}'::jsonb;

一般原则是,包含的对象在结构和数据内容上必须与被包含的对象匹配,在从包含的对象中丢弃一些不匹配的数组元素或对象键/值对后可能匹配。但是请记住,在执行包含匹配时,数组元素的顺序并不重要,并且实际上只考虑一次重复数组元素。

作为对结构必须匹配的一般原则的特殊例外,数组可以包含基本值:

-- This array contains the primitive string value:
SELECT '["foo", "bar"]'::jsonb @> '"bar"'::jsonb;

-- This exception is not reciprocal -- non-containment is reported here:
SELECT '"bar"'::jsonb @> '["bar"]'::jsonb;  -- yields false

jsonb 也有一个 existence 运算符,它是包含主题的一个变体:它测试字符串(作为一个 text 值给出)是否作为对象键或数组元素出现在 jsonb 值的顶层。这些示例返回 true,除非另有说明:

-- String exists as array element:
SELECT '["foo", "bar", "baz"]'::jsonb ? 'bar';

-- String exists as object key:
SELECT '{"foo": "bar"}'::jsonb ? 'foo';

-- Object values are not considered:
SELECT '{"foo": "bar"}'::jsonb ? 'bar';  -- yields false

-- As with containment, existence must match at the top level:
SELECT '{"foo": {"bar": "baz"}}'::jsonb ? 'bar'; -- yields false

-- A string is considered to exist if it matches a primitive JSON string:
SELECT '"foo"'::jsonb ? 'foo';

当涉及许多键或元素时,JSON 对象比数组更适合用于测试包含或是否存在,因为与数组不同,它们在内部针对搜索进行了优化,并且不需要线性搜索。

Tip

因为 JSON 包含是嵌套的,所以适当的查询可以跳过子对象的显式选择。例如,假设我们有一个 doc 列,在该列中包含顶层的对象,其中大多数对象包含 tags 域,该域包含子对象的数组。此查询查找既包含 "term":"paris" 又包含 "term":"food" 的子对象的条目,同时忽略 tags 数组外的任何此类键:

SELECT doc->'site_name' FROM websites
  WHERE doc @> '{"tags":[{"term":"paris"}, {"term":"food"}]}';

可以使用下面这种方式实现相同的事情:

SELECT doc->'site_name' FROM websites
  WHERE doc->'tags' @> '[{"term":"paris"}, {"term":"food"}]';

但这种方法的灵活性较差,并且通常效率也不高。

另一方面,JSON 存在运算符不是嵌套的:它只会查找 JSON 值顶层的指定键或数组元素。

各种包含和存在运算符与所有其他 JSON 运算符和函数都在 Section 9.16中记录。

8.14.4. jsonb Indexing #

GIN 索引可用于有效搜索大量 jsonb 文档(资料)中出现的键或键/值对。提供了两个 GIN “运算符类”,提供不同的性能和灵活性权衡。

jsonb_的默认 GIN 运算符类支持使用键存在运算符 _??|_和 _?&、包含运算符 _@>_以及 _jsonpath_匹配运算符 _@?_和 _@@_进行查询。(有关这些运算符实现的语义的详细信息,请参见 Table 9.46。)使用此运算符类创建索引的一个示例是:

CREATE INDEX idxgin ON api USING GIN (jdoc);

非默认 GIN 运算符类 jsonb_path_ops 不支持键存在运算符,但支持 @>@?@@。使用此运算符类创建索引的示例:

CREATE INDEX idxginp ON api USING GIN (jdoc jsonb_path_ops);

考虑从第三方网络服务检索的 JSON 文档的表的示例,其中有记录的模式定义。一个典型的文档是:

{
    "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
    "name": "Angela Barton",
    "is_active": true,
    "company": "Magnafone",
    "address": "178 Howard Place, Gulf, Washington, 702",
    "registered": "2009-11-07T08:53:22 +08:00",
    "latitude": 19.793713,
    "longitude": 86.513373,
    "tags": [
        "enim",
        "aliquip",
        "qui"
    ]
}

我们把这些文档存储在一个名为 api 的表中,在一个名为 jdocjsonb 列中。如果在此列上创建了 GIN 索引,则可以利用该索引进行诸如以下的查询:

-- Find documents in which the key "company" has value "Magnafone"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}';

但是,索引无法用于诸如以下的查询,因为尽管运算符 ? 可被索引,但它不会直接应用于已编制索引的列 jdoc

-- Find documents in which the key "tags" contains key or array element "qui"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui';

即使如此,通过适当使用表达式索引,上面的查询仍可以使用索引。如果查询 "tags" 键内的特定项很常见,那么定义一个这样的索引可能是有价值的:

CREATE INDEX idxgintags ON api USING GIN ((jdoc -> 'tags'));

现在,_WHERE_子句 _jdoc → 'tags' ? 'qui'_将被识别为可索引运算符 _?_对索引表达式 _jdoc → 'tags'_的一个应用。(可以在 Section 11.7中找到有关表达式索引的更多信息。)

查询的另一种方法是利用包含,例如:

-- Find documents in which the key "tags" contains array element "qui"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}';

jdoc 列上的一个简单 GIN 索引可以支持此查询。但请注意,这样一个索引将存储 jdoc 列中的每个键和值的副本,而前一个示例的表达式索引仅存储在 tags 键下找到的数据。虽然简单索引方法要灵活得多(因为它支持针对任何键的查询),但有针对性的表达式索引可能比简单索引更小、更快的搜索速度。

GIN 索引还支持执行 jsonpath 匹配的 @?@@ 运算符。示例为:

SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @? '$.tags[*] ? (@ == "qui")';
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @@ '$.tags[*] == "qui"';

对于这些运算符,GIN索引从 jsonpath 模式中提取 accessors_chain = constant 形式的子句,并根据这些子句中提到的键和值执行索引搜索。访问器链可能包括 ._key_[], and [_index]_ accessors. The jsonb_ops operator class also supports .* and .* 访问器,但 jsonb_path_ops 运算符类没有。

虽然 jsonb_path_ops 操作符类仅支持带有 @>@?@@ 操作符的查询,但它比默认操作符类 jsonb_ops 具有显著的性能优势。jsonb_path_ops 索引通常比针对相同数据的 jsonb_ops 索引小得多,并且搜索的特殊性更好,尤其是在查询包含在数据中频繁出现的键时。因此,搜索操作通常比使用默认操作符类时执行得更好。

jsonb_opsjsonb_path_ops GIN索引之间的技术差异在于,前者为数据中的每个键和值创建独立的索引项,而后者仅为数据中的每个值创建索引项。 [7 ]基本上,每个 jsonb_path_ops 索引项都是值和导致该值的键的哈希;例如,要索引 {"foo": {"bar": "baz"}} ,将创建单个索引项,并将三个 foobarbaz 全部合并到哈希值中。因此,寻找此结构的包含查询将导致极其具体的索引搜索;但根本没有办法找出 foo 是否表现为一个键。另一方面, jsonb_ops 索引将创建分别表示 foobarbaz 的三个索引项;然后执行包含查询,它将查找包含这三个项的所有行。虽然GIN索引可以相当高效地执行这样的AND搜索,但它仍然不如等效的 jsonb_path_ops 搜索具体且速度慢,尤其是如果包含任何三个索引项之一的大量行时。

jsonb_path_ops 方法的一个缺点是,它不会为不包含任何值的 JSON 结构(例如 {"a": {}})生成索引条目。如果请求搜索包含此类结构的文档,则需要进行全索引扫描,这非常慢。因此,jsonb_path_ops 不适用于经常执行此类搜索的应用程序。

jsonb 还支持 btreehash 索引。这些通常仅在检查完整 JSON 文档的相等性很重要时才有用。jsonb 数据项的 btree 排序很少受到关注,但为了完整性,它是:

Object > Array > Boolean > Number > String > Null

Object with n pairs > object with n - 1 pairs

Array with n elements > array with n - 1 elements

具有相等对数的对象按以下顺序进行比较:

key-1, value-1, key-2 ...

请注意,对象键按其存储顺序进行比较;特别是,由于较短的键存储在较长键之前,这可能导致不直观的结果,例如:

{ "aa": 1, "c": 1} > {"b": 1, "d": 1}

类似地,具有相等元素数量的数组按以下顺序进行比较:

element-1, element-2 ...

使用与底层 PostgreSQL 数据类型相同的比较规则比较原始 JSON 值。字符串使用默认数据库排序规则进行比较。

8.14.5. jsonb Subscripting #

jsonb 数据类型支持数组式下标表达式,以提取和修改元素。嵌套值可以通过链接下标表达式来表示,遵循与 jsonb_set 函数中的 path 参数相同的规则。如果 jsonb 值是一个数组,则数字下标从零开始,负整数从数组的最后一个元素向后计数。不支持切片表达式。下标表达式的结果始终为 jsonb 数据类型。

UPDATE_语句可以在 _SET_子句中使用下标修改 _jsonb_值。对于所有受影响的值,只要它们存在,就必须能够遍历下标路径。例如,如果每个 _valval['a']_和 _val['a']['b']_都是对象,则路径 _val['a']['b']['c']_可以一直遍历到 _c。如果任何 val['a']_或 _val['a']['b']_没有定义,它将被创建为一个空对象并根据需要填充。然而,如果任何 _val_本身或其中间值被定义为非对象,例如字符串、数字或 _jsonb__null,则无法进行遍历,因此会引发错误并中止事务。

下标语法的示例:

-- Extract object value by key
SELECT ('{"a": 1}'::jsonb)['a'];

-- Extract nested object value by key path
SELECT ('{"a": {"b": {"c": 1}}}'::jsonb)['a']['b']['c'];

-- Extract array element by index
SELECT ('[1, "2", null]'::jsonb)[1];

-- Update object value by key. Note the quotes around '1': the assigned
-- value must be of the jsonb type as well
UPDATE table_name SET jsonb_field['key'] = '1';

-- This will raise an error if any record's jsonb_field['a']['b'] is something
-- other than an object. For example, the value {"a": 1} has a numeric value
-- of the key 'a'.
UPDATE table_name SET jsonb_field['a']['b']['c'] = '1';

-- Filter records using a WHERE clause with subscripting. Since the result of
-- subscripting is jsonb, the value we compare it against must also be jsonb.
-- The double quotes make "value" also a valid jsonb string.
SELECT * FROM table_name WHERE jsonb_field['key'] = '"value"';

通过下标进行 jsonb 赋值以不同于 jsonb_set 的方式处理一些边缘情况。当源 jsonb 值为 NULL 时,通过下标进行赋值将进行,就像它是下标键暗示的类型(对象或数组)的空 JSON 值:

-- Where jsonb_field was NULL, it is now {"a": 1}
UPDATE table_name SET jsonb_field['a'] = '1';

-- Where jsonb_field was NULL, it is now [1]
UPDATE table_name SET jsonb_field[0] = '1';

如果为包含的元素太少的数组指定索引,则 NULL 元素将附加,直到达到索引并且可以设置值。

-- Where jsonb_field was [], it is now [null, null, 2];
-- where jsonb_field was [0], it is now [0, null, 2]
UPDATE table_name SET jsonb_field[2] = '2';

只要要遍历的最后一个现有元素是一个对象或数组(由相应的下标暗示),jsonb 值就会接受对不存在的下标路径的赋值(路径中最后一个下标指示的元素未遍历,可以是任何内容)。嵌套数组和对象结构将被创建,并且在前一种情况下,null 填充,如下标路径所示,直到可以放置赋值值。

-- Where jsonb_field was {}, it is now {"a": [{"b": 1}]}
UPDATE table_name SET jsonb_field['a'][0]['b'] = '1';

-- Where jsonb_field was [], it is now [null, {"a": 1}]
UPDATE table_name SET jsonb_field[1]['a'] = '1';

8.14.6. Transforms #

有多个附加扩展来实现针对不同过程语言的 jsonb 类型的转换。

PL/Perl 的扩展称为 jsonb_plperljsonb_plperlu。如果使用它们,jsonb 值将分别映射到 Perl 数组、哈希和标量。

PL/Python 的扩展称为 jsonb_plpython3u。如果使用它,jsonb 值将分别映射到 Python 字典、列表和标量。

在这些扩展中,jsonb_plperl 被认为是“受信任的”,即它可以由在当前数据库上具有 CREATE 权限的非超级用户安装。其余需要超级用户权限才能安装。

8.14.7. jsonpath Type #

jsonpath 类型实现对 PostgreSQL 中 SQL/JSON 路径语言的支持,以有效地查询 JSON 数据。它提供了已解析 SQL/JSON 路径表达式的二进制表示形式,该表示形式指定了路径引擎应从 JSON 数据中检索的项目,以便使用 SQL/JSON 查询函数进行进一步处理。

SQL/JSON 路径谓词和运算符的语义通常遵循 SQL。同时,为了提供处理 JSON 数据的自然方式,SQL/JSON 路径语法使用了一些 JavaScript 约定:

SQL/JSON 路径表达式中的数字文字遵循 JavaScript 规则,这在一些小细节上与 SQL 和 JSON 都不同。例如,SQL/JSON 路径允许 .11.,而这在 JSON 中无效。例如,支持非十进制整数文字和下划线分隔符, 1_000_0000x1EEE_FFFF0o2730b100101。在 SQL/JSON 路径(以及 JavaScript 中,但不是在 SQL 本身中),基数前缀之后一定不能紧跟下划线分隔符。

SQL/JSON路径表达式通常以SQL字符字符串文本形式写在SQL查询中,因此必须用单引号引起来,并且值中所需的任何单引号都必须加倍(请参阅 Section 4.1.2.1 )。某些形式的路径表达式需要它们内部的字符串文本。这些嵌入的字符串文本遵循JavaScript/ECMAScript惯例:它们必须用双引号引起来,可以在其中使用反斜杠转义来表示难以输入的字符。特别是,在嵌入式字符串文本中编写双引号的方式是 \" ,而要写入反斜杠本身,必须编写 \\ 。其他特殊反斜杠序列包括JavaScript字符串中识别的序列: \b\f\n\r\t\v 用于各种ASCII控制字符, \x_NN for a character code written with only two hex digits, \u_NNNN for a Unicode character identified by its 4-hex-digit code point, and \u{_N…​ _ 用于使用1到6个十六进制数字编写的Unicode字符代码点。

路径表达式由一系列路径元素组成,这些路径元素可以是以下任何一项:

有关将 jsonpath 表达式与 SQL/JSON 查询函数配合使用的详细信息,请参阅 Section 9.16.2

Table 8.24. jsonpath Variables

Variable

Description

$

表示正在查询的JSON值( context item )的变量。

$varname

命名变量。其值可由几个JSON处理函数的参数 vars 设置;有关详细内容,请参见 Table 9.49

@

表示过滤表达式中路径评估结果的变量。

Table 8.25. jsonpath Accessors

Accessor Operator

Description

._key_

."$_varname"_

返回具有指定键的对象成员的成员访问器。如果键名与从 $ 开始的某个命名变量匹配,或者不满足标识符的 JavaScript 规则,则必须将其用双引号引起来使其成为字符串文字。

.*

返回位于当前对象的顶层的全部成员的值的通配符成员访问器。

.**

返回当前对象的 JSON 层次结构的所有级别的全部成员值(不考虑其嵌套级别)的递归通配符成员访问器。这是 SQL/JSON 标准的 PostgreSQL 扩展。

.{_level}_

.{_start_level to end_level}_

.** 类似,但只选择 JSON 层次结构的指定级别。嵌套级别指定为整数。等级零对应于当前对象。要访问最低嵌套级别,可以使用 last 关键字。这是 SQL/JSON 标准的 PostgreSQL 扩展。

[_subscript, …​]_

数组元素访问器。 subscript 可以用两种形式给出: indexstart_index to end_index 。第一种形式按其索引返回值的单个数组元素。第二种形式通过索引范围返回值的数组切片,其中包括与提供的 start_indexend_index 相对应的元素。指定的 index 可以是整数,也可以是返回值的单个数字表达式,该表达式自动转换为整数。零索引对应于第一个数组元素。你还可以使用 last 关键字来表示最后一个数组元素,这对于处理长度未知的数组很有用。

[*]

返回所有数组元素的通配符数组元素访问器。

[7 ]出于此目的,术语“值”包括数组元素,尽管JSON术语有时认为数组元素不同于对象中的值。