↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

百科 / 数据类型 / JSON

json

文本形式的 JSON 数据

当前查看 PostgreSQL 18.6。

PG10–20 核心源码清单。类型转换与操作符类列出源码显式声明的关系;缺少记录不能排除通过其他机制进行转换或使用索引。

定义

文本形式的 JSON 数据

json
目录名称
pg_catalog.json
类型 OID
114
类型种类
基础类型
声明长度
变长(varlena)
存储策略
扩展
输入函数
json_in
输出函数
json_out

中文手册

阅读完整手册章节

阅读来源定义

8.14. JSON 类型

JSON 数据类型用于存储 JSON(JavaScript Object Notation)数据,如 RFC 7159 所定义。这类数据也可以存储为 text,但 JSON 数据类型的优势在于会强制每个存储值都符合 JSON 规则。此外,对于存储在这些数据类型中的数据,还提供了各种 JSON 专用的函数和操作符;见第 9.16 节。

PostgreSQL 提供两种用于存储 JSON 数据的类型:json 和 jsonb。为了为这些数据类型实现高效的查询机制,PostgreSQL 还提供了 jsonpath 数据类型,其说明见第 8.14.7 节。

json 和 jsonb 数据类型接收的输入值集合几乎完全相同。主要的实际区别在于效率。json 数据类型存储输入文本的精确副本,因此处理函数在每次执行时都必须重新解析;而 jsonb 数据则以分解后的二进制格式存储,由于增加了转换开销,输入时会稍慢一些,但处理起来会显著更快,因为不需要重新解析。jsonb 还支持索引,这可能是一个显著优势。

由于 json 类型存储的是输入文本的精确副本,因此它会保留词元之间在语义上无关紧要的空白,以及 JSON 对象内部键的顺序。此外,如果值中的某个 JSON 对象包含同一个键多次,所有键/值对都会被保留下来(处理函数会将最后一个值视为生效值)。相比之下,jsonb 不保留空白,不保留对象键的顺序,也不保留重复的对象键。如果输入中指定了重复的键,则只保留最后一个值。

一般而言,大多数应用都应优先将 JSON 数据存储为 jsonb,除非存在相当特殊的需求,例如遗留系统对对象键顺序的假设。

RFC 7159 规定 JSON 字符串应使用 UTF8 编码。因此,除非数据库编码是 UTF8,否则 JSON 类型不可能严格符合 JSON 规范。尝试直接包含数据库编码无法表示的字符会失败;反过来,数据库编码可以表示但 UTF8 不能表示的字符则会被允许。

RFC 7159 允许 JSON 字符串包含以 \uXXXX 表示的 Unicode 转义序列。在 json 类型的输入函数中,无论数据库编码为何,都允许 Unicode 转义,并且只检查其语法是否正确(即 \u 后面是否跟着四个十六进制数字)。但是,jsonb 的输入函数更严格:它不允许对数据库编码无法表示的字符使用 Unicode 转义。jsonb 类型还会拒绝 \u0000(因为 PostgreSQL 的 text 类型无法表示它),并且要求任何使用 Unicode 代理对来表示位于 Unicode 基本多文种平面之外字符的写法都必须正确。合法的 Unicode 转义会在存储时转换为等效的单个字符;这也包括把代理对折叠为一个字符。

注意

第 9.16 节中描述的很多 JSON 处理函数都会把 Unicode 转义转换为普通字符,因此即使它们的输入是 json 而不是 jsonb,也会抛出前面刚描述过的同类错误。json 的输入函数不做这些检查,可以视为一种历史遗留行为;不过,它确实允许在不支持所表示字符的数据库编码中,简单地存储(而不做处理)带有 JSON Unicode 转义的内容。

将 JSON 文本输入转换为 jsonb 时,RFC 7159 描述的原始类型实际上会映射为 PostgreSQL 原生类型,见表 8.23。因此,底层类型的表示范围会对合法 jsonb 数据施加一些轻微的附加限制,这些限制不适用于 json,也不适用于抽象意义上的 JSON。特别是,jsonb 会拒绝超出 PostgreSQL numeric 范围的数值,而 json 不会。RFC 7159 允许此类由实现定义的限制。不过,实际中其他实现更容易遇到这类问题,因为它们通常用 IEEE 754 双精度浮点数表示 JSON 的 number 原始类型,RFC 7159 也明确预见并允许了这种做法。与这类系统使用 JSON 交换数据时,应考虑相对于 PostgreSQL 原始存储值丢失数值精度的风险。

另一方面,正如表中所指出的那样,JSON 基本类型的输入格式还有一些轻微限制,而对应的 PostgreSQL 类型并没有这些限制。

表 8.23. JSON 基本类型及其对应的 PostgreSQL 类型

JSON 基本类型 PostgreSQL 类型 说明
string 文本 不允许 \u0000,也不允许表示数据库编码中不可用字符的 Unicode 转义
number numeric 不允许 NaN 和 infinity 值
boolean boolean 只接受小写拼写 true 和 false
null (无) SQL NULL 是不同的概念

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 值的内置函数和操作符列表,见第 9.16 节。

以 JSON 形式表示数据,可能比传统的关系数据模型灵活得多,这在需求变化较大的环境中尤其有吸引力。这两种方法完全可能在同一个应用中共存并互为补充。但是,即使对于追求最大灵活性的应用,也仍然建议 JSON 文档拥有某种相对固定的结构。这种结构通常并不受强制约束(尽管也可以用声明式方式强制某些业务规则),但具有可预测的结构会让编写查询更容易,从而能够有效地汇总表中一组“文档”(数据项)。

当 JSON 数据存储在表中时,它与任何其他数据类型一样,都要面对相同的并发控制考量。虽然存储大型文档是可行的,但要记住,任何更新都会在整行上获取一个行级锁。应考虑将 JSON 文档限制在可管理的大小,以减少更新事务之间的锁争用。理想情况下,每个 JSON 文档都应表示一个原子数据项,根据业务规则,无法再合理地将它细分为更小且可独立修改的数据项。

测试包含是 jsonb 的一项重要能力。对于 json 类型,则没有与之对应的一组功能。包含测试用于检查一个 jsonb 文档中是否包含另一个文档。除特别说明外,下面这些示例都返回真:

-- 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 还有一个存在操作符,它可看作包含的一种变体:它测试某个字符串(以 text 值给出)是否在 jsonb 值的顶层作为对象键或数组元素出现。除特别说明外,下面这些示例都返回真:

-- 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 对象比数组更适合用于测试包含或存在,因为对象与数组不同,内部已针对搜索做了优化,不需要进行线性搜索。

提示

由于 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 操作符和函数,均见第 9.16 节。

GIN 索引可用于高效搜索大量 jsonb 文档(数据项)中出现的键或键/值对。提供了两种 GIN “操作符类”,它们在性能和灵活性之间提供不同的权衡。

jsonb 的默认 GIN 操作符类支持使用键存在操作符 ?、?| 和 ?&,包含操作符 @>,以及 jsonpath 匹配操作符 @? 和 @@ 的查询。(关于这些操作符所实现语义的细节,见表 9.48。)使用此操作符类创建索引的例子如下:

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"
    ]
}

将这些文档存入名为 api 的表,使用名为 jdoc 的 jsonb 列。如果在此列上创建 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'。(表达式索引的更多信息见第 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、[*] 和 [ index ] 访问器。jsonb_ops 运算符类还支持 .* 和 .** 访问器,而 jsonb_path_ops 运算符类不支持。

虽然 jsonb_path_ops 操作符类只支持带有 @>、@? 和 @@ 操作符的查询,但相较于默认操作符类 jsonb_ops,它具有显著的性能优势。jsonb_path_ops 索引通常比相同数据上的 jsonb_ops 索引小得多,而且搜索也更有针对性,尤其是在查询中包含数据里频繁出现的键时。因此,搜索操作通常比使用默认操作符类时性能更佳。

jsonb_ops 与 jsonb_path_ops GIN 索引之间的技术差异在于,前者会为数据中的每个键和值分别创建独立的索引项,而后者只会为数据中的每个值创建索引项。[7] 基本上,每个 jsonb_path_ops 索引项都是该值连同通向该值的键一起计算出的 hash。例如,要索引 {"foo": {"bar": "baz"}},会创建一个单独的索引项,其 hash 值中同时纳入 foo、bar 和 baz 这三者。因此,查找这一结构的包含查询会得到一次非常精确的索引搜索;但完全没有办法据此找出 foo 是否作为键出现。另一方面,jsonb_ops 索引会分别创建三个索引项来表示 foo、bar 和 baz;然后为了执行包含查询,它会查找包含这三个项的行。尽管 GIN 索引可以相当高效地执行这种 AND 搜索,但它仍然会比等效的 jsonb_path_ops 搜索更不精确、也更慢,尤其是在包含这三个索引项中任意一个的行数非常多时。

jsonb_path_ops 方法的一个缺点是,它不会为不包含任何值的 JSON 结构产生索引项,例如 {"a": {}}。如果请求查找包含此类结构的文档,就需要执行一次全索引扫描,这会相当慢。因此,jsonb_path_ops 并不适合经常执行此类搜索的应用。

jsonb 还支持 btree 和 hash 索引。通常只有在需要检查完整 JSON 文档是否相等时,它们才有用。btree 对 jsonb 数据项的排序顺序通常很少受到关注,但为了完整起见,其规则如下:

Object > Array > Boolean > Number > String > null

Object with n pairs > object with n - 1 pairs

Array with n elements > array with n - 1 elements

其中有一个例外:出于历史原因,顶层空数组的排序小于 null。如果对象所含键值对数量相同,则按如下顺序比较:

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

注意,对象键按照其存储顺序进行比较;尤其是由于较短的键会先于较长的键存储,因此这可能导致一些不太直观的结果,例如:

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

同样,如果数组所含元素数量相同,则按如下顺序比较:

element-1, element-2 ...

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

jsonb 支持数组风格的下标表达式,用于提取和修改元素。可以串联下标表达式访问嵌套值,规则与 jsonb_set 函数的 path 参数相同。如果 jsonb 值是数组,数值下标从零开始;负整数从数组最后一个元素起反向计数。不支持切片表达式。下标表达式的结果始终为 jsonb 类型。

UPDATE 可在 SET 子句中使用下标修改 jsonb 值。对于所有受影响的值,路径中已存在的部分必须可以继续遍历。例如,只要 val、val['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';

还提供了一些附加扩展,为不同过程语言实现了 jsonb 类型的转换。

PL/Perl 的扩展名为 jsonb_plperl 和 jsonb_plperlu。如果使用它们,jsonb 值会按适当方式映射为 Perl 数组、hash 和标量。

PL/Python 的扩展名为 jsonb_plpython3u。如果使用它,jsonb 值会按适当方式映射为 Python 字典、列表和标量。

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

jsonpath 类型在 PostgreSQL 中实现了对 SQL/JSON 路径语言的支持,以便高效查询 JSON 数据。它提供了解析后的 SQL/JSON 路径表达式的二进制表示,该表达式指定路径引擎应从 JSON 数据中检索哪些项,以便由 SQL/JSON 查询函数做进一步处理。

SQL/JSON 路径谓词和操作符的语义通常遵循 SQL。同时,为了以更自然的方式处理 JSON 数据,SQL/JSON 路径语法采用了一些 JavaScript 约定:

  • 点号(.)用于成员访问。

  • 方括号([])用于数组访问。

  • SQL/JSON 数组从 0 开始编号,与从 1 开始的普通 SQL 数组不同。

SQL/JSON 路径表达式中的数字字面量遵循 JavaScript 规则,这在一些细节上与 SQL 和 JSON 都不同。例如,SQL/JSON 路径允许 .1 和 1.,而它们在 JSON 中是无效的。还支持非十进制整数字面量和下划线分隔符,例如 1_000_000、0x1EEE_FFFF、0o273、0b100101。在 SQL/JSON 路径中(以及 JavaScript 中,但 SQL 本身并非如此),基数前缀后面不能直接出现下划线分隔符。

SQL/JSON 路径表达式通常在 SQL 查询中写成 SQL 字符串字面量,因此它必须用单引号括起来,而值中若要出现单引号,则必须写成两个单引号(见第 4.1.2.1 节)。某些形式的路径表达式还要求其中再包含字符串字面量。这些嵌入式字符串字面量遵循 JavaScript/ECMAScript 约定:它们必须用双引号括起,并且可以在其中使用反斜杠转义来表示其他难以输入的字符。特别地,在嵌入式字符串字面量中写双引号要使用 \",写反斜杠本身则必须写成 \\。其他特殊反斜杠序列包括 JavaScript 字符串中识别的下列几种:\b、\f、\n、\r、\t、\v,用于各种 ASCII 控制字符;\xNN 表示仅用两个十六进制数字写出的字符码;\uNNNN 表示由 4 位十六进制码点标识的 Unicode 字符;\u{N...} 则表示用 1 到 6 位十六进制数字写出的 Unicode 字符码点。

路径表达式由一系列路径元素构成,这些元素可以是下列任意一种:

  • JSON 基本类型的路径字面量:Unicode 文本、数值、true、false 或 null。

  • 表 8.24中列出的路径变量。

  • 表 8.25中列出的访问器操作符。

  • jsonpath 操作符和方法,列于第 9.16.2.3 节。

  • 括号,可用于提供过滤表达式或定义路径求值顺序。

关于在 SQL/JSON 查询函数中使用 jsonpath 表达式的细节,见第 9.16.2 节。

表 8.24. jsonpath 变量

变量 说明
$ 表示正在被查询的 JSON 值的变量(上下文项)。
$varname 命名变量。它的值可以由若干 JSON 处理函数的 vars 参数设置;详见表 9.51。
@ 表示过滤表达式中路径求值结果的变量。

表 8.25. jsonpath 访问器

访问器操作符 说明

.key

."$varname"

成员访问器,用于返回指定键对应的对象成员。如果键名与某个以 $ 开头的命名变量相同,或者不符合 JavaScript 对标识符的规则,就必须用双引号将其括起,使其成为字符串字面量。

.*

通配符成员访问器,返回当前对象顶层所有成员的值。

.**

递归通配符成员访问器,处理当前对象 JSON 层次结构的所有层级,并返回所有成员值,而不论其嵌套层级如何。这是 PostgreSQL 对 SQL/JSON 标准的扩展。

.**{level}

.**{start_level to end_level}

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

[subscript, ...]

数组元素访问器。subscript 可以用两种形式给出:index 或 start_index to end_index。第一种形式按下标返回单个数组元素。第二种形式按下标范围返回数组切片,其中包括与给定 start_index 和 end_index 对应的元素。

指定的 index 可以是整数,也可以是返回单个数值的表达式,该数值会自动转换为整数。下标零对应第一个数组元素。你也可以使用 last 关键字来表示最后一个数组元素,这对于处理长度未知的数组很有用。

[*]

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





[7] 在这里,术语“值”也包括数组元素,尽管在 JSON 术语中,有时会把数组元素与对象中的值区分开来。

系统目录属性

此构建的源码初始化值。字段含义参见 pg_type 。包含头文件默认值;依赖构建的常量保留符号形式,不作为服务器运行时实测。

oid
114
descr
JSON stored as text
typacl
_null_
typlen
-1
typelem
0
typname
json
typsend
json_send
typtype
b
typalign
i
typarray
0
typbyval
f
typdelim
','
typinput
json_in
typmodin
-
typndims
0
typowner
POSTGRES
typrelid
0
typmodout
-
typoutput
json_out
typtypmod
-1
typanalyze
-
typdefault
_null_
typnotnull
f
typreceive
json_recv
typstorage
x
typbasetype
0
typcategory
U
typcollation
0
typisdefined
t
typnamespace
pg_catalog
typsubscript
-
typdefaultbin
_null_
array_type_oid
199
typispreferred
f
array_type_name
_json

类型转换 2

与此类型相关的显式 pg_cast 记录。PostgreSQL 还支持 pg_cast 之外的类型转换,缺少记录不能证明转换不可能。

源类型目标类型转换上下文转换方式函数
jsonjsonb赋值输入/输出0
jsonbjson赋值输入/输出0

运算符重载 6

每种操作数签名均为独立重载。实现函数和返回类型来自同一源码构建。

运算符左操作数右操作数返回类型含义实现函数
->jsontextjson获取 json 对象字段json_object_field
->>jsontexttext获取 json 对象字段并返回文本json_object_field_text
->jsonint4json获取 json 数组元素json_array_element
->>jsonint4text获取 json 数组元素并返回文本json_array_element_text
#>json_textjson按路径元素从 json 提取值json_extract_path
#>>json_texttext按路径元素从 json 提取值并返回文本json_extract_path_text

版本比较

PostgreSQL 17.11 → 18.6。属性比较不包含构建标识和说明正文;原始目录字段与源描述保留原文。

这两个样本的系统目录和结构化属性没有变化。

这些构建的文档也有差异,请查看对应版本的手册定义。

文档与源码

构建
18.6 · https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2
指纹
555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f

相关条目

全部数据类型 · 下载此版本 JSON · 最早收录的样本不代表该类型的实际引入版本。