postgres逆json_each

时间:2013-11-19 10:35:39

标签: json postgresql

我在字段中没有json文本。我有一行"text","format","keyname","...",我想以'{"value of keyname column": {"text":"value of text","format":"value of format",... }}'格式将其导出到json。在postgresql中可以吗?

我一直在查看postgis2geojson示例并已经了解了row_to_json函数。 http://www.postgresonline.com/journal/archives/267-Creating-GeoJSON-Feature-Collections-with-JSON-and-PostGIS-functions.html

此外,我一直在查看postgres json文档:http://www.postgresql.org/docs/9.3/static/functions-json.html

不幸的是,我发现没有明确涵盖我需要的功能,但json_each只是朝着相反的方向做我想做的事。一般来说,我认为postgres中的json函数是在假设只有列名可以用作键的情况下设计的。我对吗?有没有我可以使用的SQL hack来解决这个问题?谢谢你的帮助。

修改

select '"'||keyname||'":"'||row_to_json((select r from(Select text, format,
    (select username from my.users where users.id = table.uid) as username,
    machinename ) as r ))||'"'
    from my.table where id = 1;

2 个答案:

答案 0 :(得分:2)

由于版本9.4 postgres具有json_object_agg函数,这是json_each的反函数。您可以阅读文档here

如果数据如下所示:

> select * from example;
 text | format | keyname 
------+--------+---------
 foo  | bar    | a
 dead | beef   | b
(2 rows)

然后,您可以使用以下查询将所有内容聚合到具有键ab的对象中:

> select json_object_agg(keyname, json_build_object('text', text, 'format', format)) from example;
                                     json_object_agg                                      
------------------------------------------------------------------------------------------
 { "a" : {"text" : "foo", "format" : "bar"}, "b" : {"text" : "dead", "format" : "beef"} }
(1 row)

答案 1 :(得分:0)

为了保持API的清洁,我实际上会有所不同。你现在有这个:

select '"'||keyname||'":"'||row_to_json((select r from(Select text, format,
    (select username from my.users where users.id = table.uid) as username,
    machinename ) as r ))||'"'
    from my.table where id = 1;

你会有这个:

WITH full_r AS (select keyname, text, format, username, machinename 
                  FROM my.table JOIN my.users ON users.id = table.uid
                  WHERE id = 1),
     small_r AS (select text, format, username, machinename FROM full_r)
SELECT f.keyname, row_to_json(s)
  FROM small_r s CROSS JOIN full_r f;

这假定只返回一行。如果使用多行,则需要内连接而不是交叉连接。