从JSON中提取int,string,boolean等作为其对应的PostgreSQL类型

时间:2015-02-13 23:34:01

标签: json postgresql

我觉得我必须在这里错过一些简单的东西,但我已经查看了PostgreSQL关于JSON和JSON运算符和函数的文档,并且看不到任何解释它的内容。

在PostgreSQL中将事物变成JSON很容易:

SELECT *, pg_typeof(j) FROM (VALUES
(to_json(5)),
(to_json(true)),
(to_json('foo'::TEXT))
) x (j);

会给我一个很好的结果集json s:

   j   | pg_typeof
-------+-----------
 5     | json
 true  | json
 "foo" | json

但是,如何将这些json转换回到原始类型?当然,我不希望能够在一个结果集中完成所有操作,因为类型不一致。我只是个人意思。

我尝试了很多东西

强制转换不起作用:

SELECT to_json(5)::NUMERIC;

给出

ERROR:  cannot cast type json to numeric

如果我尝试滥用json_populate_record功能,请执行以下操作:

SELECT json_populate_record(null::INTEGER, to_json(5));

我得到了

ERROR:  first argument of json_populate_record must be a row type

在PG 9.4中,我可以很容易地告诉类型:SELECT json_typeof(to_json(5));给出了number,但这并没有帮助我实际提取它。

json_to_record(也是9.4):

SELECT * FROM json_to_record(to_json(5)) x (i INT);

给我另一个错误:

ERROR:  cannot call json_to_record on a scalar

那么如何将json“标量”(显然是PG调用它们)转换为相应的PG类型?

我对9.3和9.4感兴趣; 9.2只是奖金。

3 个答案:

答案 0 :(得分:9)

布尔值和数字的最简单方法似乎是首先转换为TEXT然后转换为适当的类型:

SELECT j::TEXT::NUMERIC
FROM (VALUES ('5.4575e6'::json)) x (j)
-- Result is 5457500, with column type NUMERIC
SELECT j::TEXT::BOOLEAN
FROM (VALUES ('true'::json)) x (j)
-- Result is t, with column type BOOLEAN

这会留下字符串,您可以在此处获取引用的值:

SELECT j::TEXT
FROM (VALUES (to_json('foo'::TEXT))) x (j)
-- Result is "foo"

显然,我的问题的这一部分has already been addressed。您可以通过将文本值包装在数组中然后将其解压缩来解决它:

SELECT array_to_json(array[j])->>0
FROM (VALUES (to_json('foo'::TEXT))) x (j)
-- Result is foo, with column type TEXT.

答案 1 :(得分:4)

第一步:如果您的值包含在结构中(通常是这种情况),则需要使用正确的运算符/函数来提取数据的字符串表示形式:->>(9.3 +),{{1 }(9.3+),#>>(9.3 +),json_each_text()(9.4 +)。

要在9.3中选择json数组元素的文本表示,你需要这样的东西:

json_array_elements_text()

对于标量值,您可以使用这个小技巧:

select json_array ->> indx
from   generate_series(0, json_array_length(json_array) - 1) indx

此时,处理字符串 nulls (通过这些方法将sson select ('[' || json_scalar || ']')::json ->> 0 -- ... 限制为json null)。要选择数字,您需要使用强制转换为NULL完全 1 与json的数字兼容)。要选择布尔,请使用强制转换为numeric(支持booleantrue作为输入表示。但请注意,如果不接受其输入表示,则强制转换会使查询失败。 F.ex.如果你的某些列中有一个json对象,那么该对象通常有一些键,通常是 号(但不总是),这个查询可能会失败:

false

如果您有此类数据,则需要使用select (json_object ->> 'key')::numeric from your_table (9.4 +)过滤您的选择:

json_typeof()

1 我没有检查他们的完整语法,但select (json_object ->> 'key')::numeric from your_table where json_typeof(json_object -> 'key') = 'number' 也接受科学记数法,所以从理论上讲,所有json数字都应该正确处理。

对于9.2+,此函数可以测试json值的类型:

numeric

答案 2 :(得分:1)

This is question similar to yours.本质上,数据类型的基础位级表示是不兼容的,并且由于涉及的含糊不清,将标量转换为本机类型并不是已实现的。 JSON有一个非常严格的规范,与javascript对象和本机密切对应。

有可能,但我认为它尚未实施。