SQL/JSON 构造函数
此补丁介绍了 JSON 的 SQL/JSON 标准构造函数:
JSON() JSON_ARRAY() JSON_ARRAYAGG() JSON_OBJECT() JSON_OBJECTAGG()
复制
在大多数情况下,这些提供了模仿现有的 json/jsonb 函数功能,但是它们也提供了一些有用的附加功能。除了文本输入,JSON() 函数接受 bytea 输入,它将从中解码并构造一个 json 值,其他功能为处理重复键提供了有用的选项和空值。这一系列补丁之后将有一个综合修补文档。
在 Andrew Dunstan 提交另一个补丁之前,该补丁是这个(以及下一个)更改的基础。所以这个想法是 SQL/JSON 是处理 SQL 数据库中的 json 值相关的标准。
PostgreSQL支持 json/jsonb 已经有一段时间了(它是在 2012 年的 Pg 9.2 中添加的!),但现在我们将获得更多支持以标准化方式访问/创建/处理这些,让我们看看我们现在能做什么。
据我所知,所有列出的 JSON*“函数”都会从一些输入中生成 json 值。
我写的是“函数”而不是函数,因为这些不是函数——psql 的 \df JSON* 没有列出它们。更重要的是,我没有看到任何相关文档,所以我能弄清楚的只是基于回归测试。
让我们看一些例子:
=$ select json(); ERROR: syntax error at or near ")" LINE 1: select json(); ^ =$ select json(null); json ------ (1 row) =$ select json(1); ERROR: cannot cast type integer to json LINE 1: select json(1); ^ =$ select json(1.1); ERROR: cannot cast type numeric to json LINE 1: select json(1.1); ^ =$ select json('depesz'); ERROR: invalid input syntax for type json DETAIL: Token "depesz" is invalid. CONTEXT: JSON data, line 1: depesz =$ select json('1'); json ------ 1 (1 row) =$ select json('"depesz"'); json ---------- "depesz" (1 row) =$ select json('[1,2,3]'); json --------- [1,2,3] (1 row)
复制
好的。所以我通常可以给 json() 一个看起来像 json 的“函数”字面值,因此,我会得到输入到 json 的值。
有趣的是我也可以使用 bytea 值:
=$ select json('\x2264657065737a22'::bytea); json ────────── "depesz" (1 row)
复制
在这一刻,我不能说这是壮观的事情,在具体操作中也会面临一些选择:
- FORMAT JSON——在没有测试前,我发现除了 JSON 之外的其他值,所以我不知道这是做什么用的。
- ENCODING X – 这似乎对提供不同(来自服务器)编码的 bytea 值很有用,但我对 ISO-8859-2 数据进行了尝试,但失败了,没有像 iso8859-2、iso88592 或类似的任何值被接受, 并且测试只提到 utf* 变体。
但是有一个有趣的东西可以用于验证:WITH UNIQUE KEYS 或 WITHOUT UNIQUE KEYS。以下是它的工作原理:
=$ select JSON( '{"a": 12, "b": 23}' WITH UNIQUE KEYS ); json -------------------- {"a": 12, "b": 23} (1 row) =$ select JSON( '{"a": 12, "b": 23}' WITHOUT UNIQUE KEYS ); json -------------------- {"a": 12, "b": 23} (1 row) =$ select JSON( '{"a": 12, "a": 23}' WITH UNIQUE KEYS ); ERROR: duplicate JSON object key value =$ select JSON( '{"a": 12, "a": 23}' WITHOUT UNIQUE KEYS ); json -------------------- {"a": 12, "a": 23} (1 row)
复制
因此,我选择 JSON() 构造函数,并为其提供具有非唯一键的对象数据,但我将添加“WITH UNIQUE KEYS”,它将失败。
好的。让我们切换到下一个:JSON_ARRAY。这其实更有趣。我们可以从简单的开始:
=$ select json_array(1,2,3); json_array ------------ [1, 2, 3] (1 row)
复制
然后,我们可以:
=$ select JSON_ARRAY( 1, '12', 'hubert', 'depesz' ); json_array ------------------------------- [1, "12", "hubert", "depesz"] (1 row)
复制
或者甚至是做如下操作:
=$ select json_array( 1, 2, json_array('hubert','depesz','lubaczewski'), json('{}') ); json_array ------------------------------------------------- [1, 2, ["hubert", "depesz", "lubaczewski"], {}] (1 row)
复制
现在,我们也可以让它返回 jsonb 类型:
=$ select json_array( 1, 2, json_array('hubert','depesz','lubaczewski'), json('{}') returning jsonb) \gdesc Column | Type ------------+------- json_array | jsonb (1 row)
复制
有趣的是,您可以直接选择:
=$ select json_array( select datname from pg_database order by datname returning jsonb ); json_array ----------------------------------------------------------- ["depesz", "pgdba", "postgres", "template0", "template1"] (1 row)
复制
同样,您现在也可以使用 json_arrayagg:
=$ select json_arrayagg(datname order by datname) from pg_database; json_arrayagg ----------------------------------------------------------- ["depesz", "pgdba", "postgres", "template0", "template1"] (1 row)
复制
接下来是 JSON_OBJECT()。这也很有趣:
=$ SELECT JSON_OBJECT( 'a': 123, 'b': json_array(1,2,3)); json_object ------------------------------ {"a" : 123, "b" : [1, 2, 3]} (1 row)
复制
就像使用 JSON_ARRAY 一样,我可以使用 RETURNING JSONB 来获取 jsonb:
=$ SELECT JSON_OBJECT( relname: relkind returning JSONB) from pg_class limit 1; json_object ----------------------- {"pg_statistic": "r"} (1 row)
复制
就像 JSON_ARRAY 和它的聚合器一样,我们有 JSON_OBJECTAGG:
=$ select JSON_OBJECTAGG( datname: oid) from pg_database; json_objectagg --------------------------------------------------------------------------------------------------- { "postgres" : "5", "pgdba" : "16394", "template1" : "1", "template0" : "4", "depesz" : "16395" } (1 row)
复制
这看起来很棒,不要误会我的意思:我仍然认为 db 中的 json 经常被滥用,并导致诸如“我如何从 json 字段中的嵌套数组中获取数据”之类的问题提出,这些问题在 IRC、Slack 或 Reddit 上经常出现。
我喜欢基于键/值对制作正确的 jsonb 对象是多么容易,适当引用和处理特殊情况。但是 - json 支持不会消失,新添加的内容看起来还不错。