使用JSON数据
使用JSON数据¶
SeaboxMPP数据库支持json
和jsonb
数据类型来存储JSON (JavaScript Object Notation)数据。
SeaboxMPP数据库按照文档RFC 7159支持JSON,并且根据JSON规则强制数据有效性。也有一些用于json
和jsonb
数据类型的JSON相关的函数和操作符。
SeaboxMPP数据库包含创建和操作JSON数据的内置函数和运算符。
注意:对于json
数据类型值,即使JSON对象包含重复的键,也会保留所有键/值对。对于重复的键,JSON处理函数将最后一个值视为可操作的值。对于JSONB数据类型,不保留重复的对象键。如果输入包含重复键,则只保留最后一个值。请参见关于JSON数据。
关于JSON数据¶
SeaboxMPP数据库支持两种JSON数据类型: json
和 jsonb
. 他们输入值基本一致,主要区别之一是效率。
-
json
数据类型存储输入副本. 这要求JSON处理函数每次执行时处理json
数据。json
数据类型不会修改输入文本。-
记号之间没有语义意义的空格被保留,JSON对象内的键的顺序也被保留。
-
即便JSON对象含有重复键,所有的键/值对也会被保留。对于重复键,JSON处理函数把其中的最后一个值当作有效值。
-
-
jsonb
数据类型存储输入文本的二进制格式。输入数据的转换开销使jsonb稍慢于json
数据类型. 但是,json处理函数明显更快,因为解析jsonb
数据不是必须的。jsonb
数据类型修改输入文本。-
空格不保留
-
对象内的键的顺序不保留
-
重复键对象不保留,如果输入包含重复键,仅保留最后一个值。
-
SeaboxMPP数据库jsonb
数据类型支持GIN, btree,和hash索引。
一般来说,JSON数据应该存储为jsonb
数据类型,除非特殊需要,例如关于对象键顺序的遗留假设。
- JSON数据中的Unicode字符说明如下:
RFC 7159文档允许JSON字符串包含表示为\uXXXX
的Unicode转义序列。不过,SeaboxMPP对每一个数据库只允许一种字符集编码。
除非数据库编码为UTF8,json
类型不可能严格地符合JSON说明。尝试包括数据库编码中无法表示的字符将会失败。允许可在数据库编码中表示但不在UTF8中的字符。
- `json`数据类型的SeaboxMPP数据库输入函数允许unicode转义,而无论是什么数据库编码,只检查unicode转义的语法正确性(`\u`后跟四个十六进制数字)。
- `jsonb`数据类型的SeaboxMPP数据库输入函数更严格。它不允许非ASCII字符(`U+007F`以上的字符)使用Unicode转义,除非数据库编码是UTF8。它还拒绝`\u0000`,它不能在SeaboxMPP数据库`text`类中表示,并且它要求使用unicode代理项对指定unicode基本多语言平面之外的字符是正确的。有效的Unicode转义符(除了`\u0000`)转换为等效的ASCII或UTF8字符进行存储;这包括将代理项对折叠为单个字符。
注意:JSON函数和运算符中描述的许多JSON处理函数将Unicode转义转换为常规字符。函数对数据库编码中无法表示的字符抛出错误。如果可能的话,应该避免将JSON中的Unicode转义与非UTF8数据库编码混合在一起。
- JSON数据类型与SeaboxMPP数据类型的映射说明如下:
当将JSON文本的数据转换为jsonb
数据时,RFC 7159描述的原始数据类型可映射为SeaboxMPP数据库中的数据类型如下表所示。
表 将JSON数据类型映射到SeaboxMPP数据类型
JSON原始数据类型 | SeaboxMPP数据库数据类型 | 注意 |
---|---|---|
string |
text |
不允许使用\u0000 。只有当数据库编码为utf8时,才允许使用非ASCII Unicode转义。 |
number |
numeric |
不允许使用NaN 和infinity 值 |
boolean |
boolean |
只接受小写的正误拼写 |
null |
(none) | The JSON null 原始类型不同于SQL NULL 。 |
对于有效的jsonb
数据的构成有一些次要的约束,这些约束既不适用于json
数据类型,也不适用于抽象的JSON,对应于基础数据类型所能表示的限制。值得注意的是,当将数据转换为jsonb
数据类型时,超出SeaboxMPP数据库numeric
数据类型范围的数字将被拒绝,而json
数据类型不会拒绝这些数字。
RFC 7159允许这种实施定义的限制。然而,在实践中,这些问题可能会出现在其他实现中,因为通常将JSON原始类型number
表示为IEEE 754双精度浮点(RFC7159明确预测并允许)。
当使用JSON作为与其他系统的交换格式时,请注意与SeaboxMPP数据库最初存储的数据相比,数字精度可能会降低。
另外,正如上表中所指出的,对于JSON原语类型的输入格式,存在一些小的限制,这些限制不适用于相应的SeaboxMPP数据库数据类型。
输入输出语法¶
json
数据类型的输入和输出语法如RFC 7159中所述。
下列都是合法的json
表达式:
-- 简单标量/原始值
-- 原始值值可以是数字、带引号的字符串、true、false或者null SELECT '5'::json;
-- 零个或者更多个元素的数组(元素类型可以不同)
SELECT '[1, 2, "foo", null]'::json;
-- 含有键/值对的对象
-- 注意对象的键必须总是带引号的字符串
SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json;
-- 数组和对象可以任意嵌套
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
数据类型,将根据基础数字类型的行为打印数字。在实践中,这意味着使用e符号输入的数字将不使用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使用设计原则¶
将数据表示为JSON比传统关系数据模型要更灵活,在需求变化的环境中表现得尤其明显。在同一个应用中很可能两种方法会共存并且成为彼此的互补。不过,即便是对于要求最大灵活性的应用中,我们仍然推荐JSON有些许固定的结构。这种结构是非强制的(尽管可能会强制一些业务规则),但是如果有可预测的结构会让编写有效汇总表中一组“文档”(数据)的查询更容易。
在表中存储时,JSON数据服从和其他任何数据类型一样的并发控制考虑。尽管存储大型文档格式可行的,但要记住任何更新都要求整个行上的一个行级锁。为了降低更新事务之间的锁竞争,请考虑限制JSON文档为一个可管理的尺寸。理想上,每个JSON文档应该表示业务规则规定的一个原子数据,并且不能进一步地被分解为更小的可以独立修改的数据。
jsonb容器¶
测试容器是jsonb
的一项重要功能。 json
类型没有并行的设施集。容器测试一个jsonb
文档中是否包含了另一个jsonb
文档。这些示例返回true,除非另有标注:
--简单标量/原始数值仅包含相同的值:
SELECT '"foo"'::jsonb @> '"foo"'::jsonb;
-- 右边的数组包含在左边的数组中:
SELECT '[1, 2, 3]'::jsonb @> '[1, 3]'::jsonb;
--数组元素的顺序并不重要,因此这也是正确的:
SELECT '[1, 2, 3]'::jsonb @> '[3, 1]'::jsonb;
-- 重复的数组元素也不重要:
SELECT '[1, 2, 3]'::jsonb @> '[1, 2, 2]'::jsonb;
-- 右侧只有一对的对象包含在左侧的对象中:
SELECT '{"product": "SeaboxMPP", "version": "6.0.0", "jsonb":true}'::jsonb @> '{"version":"6.0.0"}'::jsonb;
--右侧的数组被认为不包含在左侧的数组中,即使其中嵌套了类似的数组:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[1, 3]'::jsonb; -- yields false
--但是,通过一层嵌套,它包含:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[[1, 3]]'::jsonb;
--同样,此处未报告遏制:
SELECT '{"foo": {"bar": "baz", "zig": "zag"}}'::jsonb @> '{"bar": "baz"}'::jsonb; -- yields false
-- 但是,通过一层嵌套,它包含:
SELECT '{"foo": {"bar": "baz", "zig": "zag"}}'::jsonb @> '{"foo": {"bar": "baz"}}'::jsonb;
一般原则是,所包含的对象必须在结构和数据内容方面与包含的对象匹配,可能是在从包含的对象中丢弃一些不匹配的数组元素或对象键/值对之后。 对于容器,在进行容器匹配时,数组元素的顺序并不重要,重复的数组元素只被有效地考虑一次。
作为结构必须匹配的一般原则的例外,数组可以包含原始值:
-- 此数组包含原始字符串值::
SELECT '["foo", "bar"]'::jsonb @> '"bar"'::jsonb;
-- 这个异常不是相互的——这里报告了非包容::
SELECT '"bar"'::jsonb @> '["bar"]'::jsonb; -- yields false
jsonb
还有一个扩展操作符,它是容器主题的变体:它测试字符串(作为文本值给出)是否作为对象键或数组元素出现在jsonb
值的顶层。这些示例返回true,,除非另有标注:
-- 字符串作为数组元素存在:
SELECT '["foo", "bar", "baz"]'::jsonb ? 'bar';
-- 字符串作为对象键存在:
SELECT '{"foo": "bar"}'::jsonb ? 'foo';
-- 不考虑对象值:
SELECT '{"foo": "bar"}'::jsonb ? 'bar'; -- yields false
-- 与容器一样,存在必须在顶层匹配:
SELECT '{"foo": {"bar": "baz"}}'::jsonb ? 'bar'; -- yields false
-- 如果字符串与原始JSON字符串匹配,则认为该字符串存在:
SELECT '"foo"'::jsonb ? 'foo';
当涉及到许多键或元素时,JSON对象比数组更适合测试包含性或存在性,因为与数组不同,JSON对象在内部针对搜索进行了优化,不需要进行线性搜索。
各种容器和存在操作符以及所有其他JSON操作符和函数都记录在JSON函数和操作符JSON函数和操作符中。
因为JSON容器是嵌套的,所以适当的查询可以跳过子对象的显式选择。例如,假设我们有一个包含顶级对象的doc列,其中大多数对象包含子对象数组的标记字段。此查询查找包含"term":"paris"
和"term":"food"
的子对象出现的条目,同时忽略标记数组之外的任何此类键:
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值的顶层查找指定的键或数组元素。
jsonb数据GIN索引¶
可以使用GIN索引有效地搜索出现在大量jsonb
文档(基准)中的键或键/值对。两个GIN操作符类,提供不同的性能和灵活性权衡。
jsonb
的默认GIN操作符类支持带@>
, ?
, ?&
和 ?|
操作符的查询。
CREATE INDEX idxgin ON api USING gin (jdoc);
非默认的GIN运算符类jsonb_path_ops
仅支持为@>
运算符编制索引。使用此运算符类创建索引的示例如下:
CREATE INDEX idxginp ON api USING gin (jdoc jsonb_path_ops);
考虑一个表的示例,该表存储从第三方Web服务检索到的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"
]
}
JSON文档存储在jsonb
列中的一个名为API的表中。如果在此列上创建了GIN索引,则以下查询可以使用该索引:
-- 查找关键词“公司”具有“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'
。有关表达式索引的信息,请参阅表达式索引表达式索引。
查询JSON文档的另一种方法是利用包含性,例如:
-- 查找键“tags”包含数组元素"qui"的文档
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}';
jdoc
列上的一个简单的GIN索引可以支持这个查询。但是,索引将在jdoc
列中存储每个键和值的副本,而前一个示例的表达式索引只存储标记键下的数据。虽然简单索引方法要灵活得多(因为它支持关于任何键的查询),但是目标表达式索引可能比简单索引更小,搜索速度更快。
尽管 jsonb_path_ops
类只支持带@>
运算符的查询,但它比默认的jsonb_operator类具有性能优势。对于相同的数据,jsonb_path_ops
索引通常比jsonb_ops索引小得多,搜索的特殊性更好,尤其是当查询包含频繁出现在数据中的键时。因此,搜索操作通常比默认的operator类执行得更好。
jsonb_ops
和 jsonb-path-ops-gin
索引的技术区别在于前者为数据中的每个键和值创建独立的索引项,而后者仅为数据中的每个值创建索引项。
注意:对于这个讨论,术语value包括数组元素,尽管JSON术语有时考虑数组元素不同于对象中的值。
基本上,每个jsonb_path_ops
索引项都是值的散列和指向该值的键;例如,要索引{"foo": {"bar":"baz"}}
,将创建一个索引项,将foo
, bar
, 和baz
中的三个都合并到散列值中。因此,查找此结构的包含查询将导致极其具体的索引搜索;但根本无法确定foo是否显示为键。另一方面,jsonb_ops
索引将分别创建三个表示foo
, bar
, 和baz
的索引项;然后,为了执行包含性查询,它将查找包含这三个项的行。虽然GIN索引可以相当有效地执行这样的搜索,但是它仍然比同等的jsonb_path_ops
搜索更不具体和更慢,特别是如果有大量的行包含三个索引项中的任何一个。
jsonb_path_ops
方法的一个缺点是它不会为不包含任何值的json结构生成索引项,例如{"a":{}}
:。如果请求搜索包含此类结构的文档,则需要进行完全索引扫描,这非常慢。jsonb_path_ops
不适合经常执行这种搜索的应用程序。
jsonb数据btree索引和哈希索引¶
jsonb
还支持btree
和hash
索引。只有在检查完整JSON文档的相等性很重要时,这些方法才有用。
为完整起见,josonb
基准的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 ...
使用与底层SeaboxMPP数据库数据类型相同的比较规则来比较原始JSON值。使用默认数据库排序规则比较字符串。
JSON操作符¶
这个表格描述了可以用于json
和 jsonb
数据类型的操作符。
表 json
和 jsonb
操作符
操作符 | 右操作数类型 | 描述 | 示例 | 示例结果 |
---|---|---|---|---|
-> |
int |
获得JSON数组元素(索引从零开始)。 | '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 |
{"c":"baz"} |
-> |
text |
根据键获得JSON对象的域。 | '{"a": {"b":"foo"}}'::json->'a' |
{"b":"foo"} |
->> |
int |
获得JSON数组元素的text 形式。 |
'[1,2,3]'::json->>2 |
3 |
->> |
text |
获得JSON对象域的text 形式。 |
'{"a":1,"b":2}'::json->>'b' |
2 |
#> |
text[] |
获得在指定路径上的JSON对象。 | '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b} ' |
{"c": "foo"} |
#>> |
text[] |
获得在指定路径上的JSON对象的text 形式。 |
'{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}' |
3 |
注意: 对于json
和jsonb
数据类型,这些运算符都有并行变体。字段、元素和路径提取运算符返回的数据类型与其左侧输入(json
和jsonb
)相同,但指定为返回text
的数据类型除外,后者将值强制为text
。如果JSON输入没有与请求匹配的正确结构,则字段、元素和路径提取运算符返回NULL
,而不是失败;例如,如果不存在这样的元素。
下表描述了需要jsonb
数据类型作为左操作数的运算符。这些运算符中的许多都可以通过jsonb
运算符类进行索引。有关jsonb
包含和存在语义的完整描述,请参见jsonb容器与存在。有关如何使用这些运算符有效地索引JSONB数据的信息,请参阅jsonb索引。
表 jsonb
操作符
操作符 | 右操作数类型 | 描述 | 示例 |
---|---|---|---|
@> |
jsonb |
左边的json值包含右边的值吗? | '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb |
<@ |
jsonb |
左JSON值是否包含在右值中? | '{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb |
? |
text |
键/元素字符串是否存在于JSON值中? | '{"a":1, "b":2}'::jsonb ? 'b' |
?\| |
text[] |
是否存在这些键/元素字符串? | '{"a":1, "b":2, "c":3}'::jsonb ?\| array['b', 'c'] |
?& |
text[] |
所有这些键/元素字符串都存在吗? | '["a", "b"]'::jsonb ?& array['a', 'b'] |
下表中的标准比较运算符仅适用于 jsonb
数据类型,而不适用于 json
数据类型。它们遵循jsonb
索引jsonb索引中描述的B树操作的排序规则。
表 jsonb
比较运算符
操作符 | 描述 |
---|---|
< |
小于 |
> |
大于 |
<= |
小于或等于 |
>= |
大于或等于 |
= |
等于 |
<> 或者!= |
不等于 |
注意: 这个!=
运算符在解析阶段转换为 <>
。无法执行!=
和<>
来执行不同操作的运算符。
JSON创建函数¶
此表描述了创建 json
数据类型值的函数。(目前, jsonb
没有等价的函数,但是您可以将其中一个函数的结果强制转换为jsonb
。)
to_json(anyelement)
- 描述
- 返回该值作为一个合法的JSON对象。 数组和组合会被递归处理并且转换成数组和对象。如果输入包含一个从该类型到 json的转换,会使用该cast函数来执行转换,否则将会产生一个JSON标量值。对于任何非数字、布尔值或空值的标量类型,会使用其文本表示,并且加上适当的引号和转义让它变成一个合法的JSON字符串。
- 示例
to_json('Fred said "Hi."'::text)
- 示例结果
"Fred said \"Hi.\""
array_to_json(anyarray [, pretty_bool])
- 描述
- 返回该数组为一个JSON数组。一个SeaboxMPP数据库多维数组会变成一个JSON数组的数组。 如果pretty_bool 为true,在第一维元素之间会增加换行。
- 示例
array_to_json('{{1,5},{99,100}}'::int[])<
- 示例结果
[1,5],[99,100]
row_to_json(record [, pretty_bool])
- 描述
- 返回该行为一个JSON对象。如果pretty_bool pretty_bool为true,在第一级别元素之间会增加换行。
- 示例
row_to_json(row(1,'foo'))
- 示例结果
{"f1":1,"f2":"foo"}
json_build_array(VARIADIC "any")
- 描述
- 从VARIADIC 参数列表构建一个可能是异种类型的JSON数组。
- 示例
json_build_array(1,2,'3',4,5)
- 示例结果
[1, 2, "3", 4, 5]
json_build_object(VARIADIC "any")
- 描述
- 从VARIADIC参数列表构建JSON对象。参数列表按顺序获取,并转换为一组键/值对。
- 示例
json_build_object('foo',1,'bar',2)
- 示例结果
{"foo": 1, "bar": 2}
- json_object(text[])
- 描述
- 从文本数组构建JSON对象。数组必须是一维或二维数组。一维数组必须有偶数个元素。元素作为键/值对。对于二维数组,每个内部数组必须恰好有两个元素,作为键/值对。
- 示例
-
json_object('{a, 1, b, "def", c, 3.5}')
json_object('{{a, 1},{b, "def"},{c, 3.5}}')
- 示例结果
{"a": "1", "b": "def", "c": "3.5"}
json_object(keys text[], values text[])
- 描述
- 从文本阵列中创建JSON对象。这一形式的json_object对象从两个分隔阵列中选择了键和值对。在所有其他方面,它与一个论据形式相同。
- 示例
json_object('{a, b}', '{1,2}')
- 示例结果
{"a": "1", "b": "2"}
注意:
array_to_json
和row_to_json
的行为与to_json
相同,只是提供了一个打印漂亮的选项。to_json描述的行为同样适用于其他JSON创建函数转换的每个单独的值。
注意:hstore模块包含从
hstore转换为
json的函数,因此通过
json创建函数转换的
hstore`值将被表示为json对象,而不是原始字符串值。
JSON聚合函数¶
此表显示函数将记录聚合到一个JSON对象数组和一对JSON对象的值。
表 JSON聚合函数
函数 | 参数类型 | 返回类型 | 描述 |
---|---|---|---|
json_agg(record) |
record |
json |
将记录聚合为对象的JSON数组。 |
json_object_agg(name, value) |
("any", "any") |
json |
将名称/值对聚合为JSON对象。 |
JSON处理函数¶
这个表描述处理json
和 jsonb
值的函数。
许多处理函数和运算符将JSON字符串中的Unicode转义符转换为适当的单个字符。如果输入数据类型是jsonb
,这不是问题,因为转换已经完成。但是,对于json
数据类型输入,这可能导致抛出错误。请参见关于
关于JSON数据。
json_array_length(json),jsonb_array_length(jsonb)
- 返回类型
- int
- 描述
- 返回最外层JSON数组中的元素数。
- 示例
json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]')
- 示例结果
- 5
json_each(json),jsonb_each(jsonb)
- 返回类型
-
setof key text, value json
setof key text, value jsonb
- 描述
- 将最外层的JSON对象展开为一组键/值对。
- 示例
select * from json_each('{"a":"foo", "b":"bar"}')
示例结果
key | value
-----+-------
a | "foo"
b | "bar"</code></pre></td>
json_each_text(json),jsonb_each_text(jsonb)
- 返回类型
- setof key text, value text
- 描述
- 把最外层的JSON对象展开成键/值对的集合。返回值的类型是text。
- 示例
select * from json_each_text('{"a":"foo", "b":"bar"}')
示例结果
key | value
-----+-------
a | foo
b | bar
json_extract_path()
- 用法
json_extract_path(from_json json, VARIADIC path_elems text[]),jsonb_extract_path(from_json jsonb, VARIADIC path_elems text[])
- 返回类型
- json,jsonb
- 描述
- 返回path_elems指定的JSON值。等效于#>操作符。
- 示例
json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4')
- 示例结果
{"f5":99,"f6":"foo"}
json_extract_path_text(from_json json, VARIADIC path_elems text[]),jsonb_extract_path_text(from_json jsonb, VARIADIC path_elems text[])
- 返回类型
- text
- 描述
- 以文本形式返回path_elems指向的JSON值。相当于>>运算符。
- 示例
json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4','f6')
- 示例结果
- foo
json_object_keys(json),jsonb_object_keys(jsonb)
- 返回类型
- setof text
- 描述
- 返回最外层JSON对象中的键集合。
- 示例
json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}')
- 示例结果
- ```
json_object_keys
f1 f2 ```
json_populate_record(base anyelement, from_json json), jsonb_populate_record(base anyelement, from_json jsonb)
- 返回类型
- anyelement
- 描述
- 把from_json的对象展开成一行,其中的列匹配由base定义的记录类型。
- 示例
select * from json_populate_record(null::myrowtype,'{"a":1,"b":2}')
- 示例结果
a | b ---+--- 1 | 2
json_populate_recordset(base anyelement, from_json json), jsonb_populate_recordset(base anyelement, from_json jsonb)
- 返回类型
- setof anyelement
- 描述
- 将from_json的最外层数组从json扩展到一组行,这些行的列与基定义的记录类型匹配。
- 示例
select * from json_populate_recordset(null::myrowtype, '[{"a":1,"b":2},{"a":3,"b":4}]')
- 示例结果
a | b ---+--- 1 | 2 3 | 4
json_array_elements(json),jsonb_array_elements(jsonb)
- 返回类型
- setof json,setof jsonb
- 描述
- 将JSON数组扩展为一组JSON值。
- 示例
select * from json_array_elements('[1,true, [2,false]]')
- 示例结果
- ```
value
1 true [2,false] ```
json_array_elements_text(json),jsonb_array_elements_text(jsonb)
- 返回类型
- setof text
- 描述
- 将JSON数组扩展为一组文本值。
- 示例
select * from json_array_elements_text('["foo", "bar"]')
- 示例结果
- ```
value
foo bar ```
json_typeof(json),jsonb_typeof(jsonb)
- 返回类型
- text
- 描述
- 以文本字符串形式返回最外面的JSON值的类型。可能的类型包括object, array, string, number, boolean, 和 null。
- 示例
json_typeof('-123.4')
- 示例结果
- number
json_to_record(json),jsonb_to_record(jsonb)
- 返回类型
- record
- 描述
- 从JSON对象生成任意记录,与所有返回记录的函数一样,调用方必须使用AS子句显式定义记录的结构。
- 示例
select * from json_to_record('{"a":1,"b":[1,2,3],"c":"bar"}') as x(a int, b text, d text)
- 示例结果
a | b | d ---+---------+--- 1 | [1,2,3] |</code></pre></td>
json_to_recordset(json),jsonb_to_recordset(jsonb)
- 返回类型
- setof record
- 描述
- 从JSON对象数组生成任意记录集,与所有返回记录的函数一样,调用方必须使用AS clause子句显式定义记录的结构。
- 示例
select * from json_to_recordset('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]') as x(a int, b text);
- 示例结果
a | b ---+----- 1 | foo 2 |
注意:
-
函数
json_populate_record()
,json_populate_recordset()
,json_to_record()
和json_to_recordset()
的示例使用常量。但是,典型的用法是引用
FROM
子句中的表,并使用它的json
或jsonb
列之一作为函数的参数。然后可以在查询的其他部分中引用提取的键值。例如,可以在WHERE子句和目标列表中引用该值。以这种方式提取多个值可以提高性能,而不是使用每个键操作符分别提取多个值。JSON键与目标行类型中相同的列名匹配。这些函数的JSON类型强制可能不会产生某些类型所需的值。目标行类型中未出现的JSON字段将从输出中省略,不匹配任何JSON字段的目标列将为空。
-
json_typeof
函数NULL返回值null
不应与SQLNULL
混淆。当调用json_typeof('null'::json)
将返回null
时,调用json_typeof(NULL::json)
将返回SQLNULL
。