在Postgres(版本9.6)中将任何文本(或varchar)转换为jsonB
类型的正确方法是什么?
例如,我在这里使用两种方法,结果不同:
方法1:
dev=# select '[{"field":15,"operator":0,"value":"1"},{"field":15,"operator":0,"value":"2"},55]'::jsonb;
jsonb
----------------------------------------------------------------------------------------------
[{"field": 15, "value": "1", "operator": 0}, {"field": 15, "value": "2", "operator": 0}, 55]
(1 row)
方法2,它不能产生预期的结果,顺便说一下:
dev=# select to_jsonb('[{"field":15,"operator":0,"value":"1"},{"field":15,"operator":0,"value":"2"},55]'::text);
to_jsonb
----------------------------------------------------------------------------------------------------
"[{\"field\":15,\"operator\":0,\"value\":\"1\"},{\"field\":15,\"operator\":0,\"value\":\"2\"},55]"
(1 row)
dev=#
这里,它被转换为字符串,而不是数组。 为什么第二种方法不能创建数组?
答案 0 :(得分:6)
<强> to_jsonb(anyelemnt)强>
以json或jsonb的形式返回值。阵列和复合材料是 转换(递归)到数组和对象;否则,如果有的话 从类型转换为json,将使用转换函数 执行转换;否则,产生标量值。任何 除了数字,布尔值或空值之外的标量类型,文本 将使用表示形式,使其成为有效的json 或jsonb值。
恕我直言,你提供了一个JSON格式的字符串,那么你应该使用第一种方法。
to_json('Fred said "Hi."'::text) --> "Fred said \"Hi.\""
如果您尝试使用to_json(text)获取元素数组,则会出现下一个错误:
select *
from jsonb_array_elements_text(to_jsonb('[{"field":15,"operator":0,"value":"1"},{"field":15,"operator":0,"value":"2"},55]'::text));
无法从标量中提取元素
但如果你之前把它投到了json:
select *
from jsonb_array_elements_text(to_jsonb('[{"field":15,"operator":0,"value":"1"},{"field":15,"operator":0,"value":"2"},55]'::json));
+--------------------------------------------+
| value |
+--------------------------------------------+
| {"field": 15, "value": "1", "operator": 0} |
+--------------------------------------------+
| {"field": 15, "value": "2", "operator": 0} |
+--------------------------------------------+
| 55 |
+--------------------------------------------+
答案 1 :(得分:1)
如果您的文本只是json格式的文本,则可以像这样将其显式转换为json / jsonb:
选择'{“ a”:“ b”}':: jsonb
答案 2 :(得分:0)
开放数据应用程序中的典型解析问题是将CSV(或类似CSV)文本逐行解析为JSONB正确(原子)数据类型。数据类型可以用SQL行话(“ int”,“ text”,“ float”等)或JSON行话(“ string”,“ number”)定义:
CREATE FUNCTION csv_to_jsonb(
p_info text, -- the CSV line
coltypes_sql text[], -- the datatype list
rgx_sep text DEFAULT '\|' -- CSV separator, by regular expression
) RETURNS JSONb AS $f$
SELECT to_jsonb(a) FROM (
SELECT array_agg(CASE
WHEN tp IN ('int','integer','smallint','bigint') THEN to_jsonb(p::bigint)
WHEN tp IN ('number','numeric','float','double') THEN to_jsonb(p::numeric)
WHEN tp='boolean' THEN to_jsonb(p::boolean)
WHEN tp IN ('json','jsonb','object','array') THEN p::jsonb
ELSE to_jsonb(p)
END) a
FROM regexp_split_to_table(p_info,rgx_sep) WITH ORDINALITY t1(p,i)
INNER JOIN unnest(coltypes_sql) WITH ORDINALITY t2(tp,j)
ON i=j
) t
$f$ language SQL immutable;
-- Example:
SELECT csv_to_jsonb(
'123|foo bar|1.2|true|99999|{"x":123,"y":"foo"}',
array['int','text','float','boolean','bigint','object']
);
-- results [123, "foo bar", 1.2, true, 99999, {"x": 123, "y": "foo"}]
-- that is: number, string, number, true, number, object