将Postgres表导出为json


35

有没有一种方法可以将Postgres表数据作为json导出到文件中?我需要将输出逐行显示,例如:

{'id':1,'name':'David'}
{'id':2,'name':'James'}
...

编辑:postgres版本:9.3.4

Answers:


48

试试这里的基本介绍,以PostgreSQLJSON

另外,PostgreSQL文档还不错,因此请在此处尝试。查看pretty_bool选项。

您最初的问题是“是否可以将postgres表数据导出为JSON”。您想要这种格式

{'id':1,'name':'David'}
{'id':2,'name':'James'}
...

我没有正在运行的实例,PostgreSQL所以我下载,编译并安装了9.4。

为了回答这个问题,我首先CREATE编辑了一张桌子(弗雷德)

CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));

INSERT INTO fred VALUES (2,    43, 'asfasfasfd'      );
INSERT INTO fred VALUES (3,   435, 'ererere'         );
INSERT INTO fred VALUES (6, 43343, 'eresdfssfsfasfae');

然后,检查:

test=# select * from fred;

 mary | jimmy |      paulie      
------+-------+------------------
    2 |    43 | asfasfasfd
    3 |   435 | ererere
    6 | 43343 | eresdfssfsfasfae

然后我发出了这个命令

test=# COPY (SELECT ROW_TO_JSON(t) 
test(# FROM (SELECT * FROM fred) t) 
test-# TO '/paulstuff/sware/db/postgres/inst/myfile';
COPY 3
test=# 

然后,我退出psql并列出文件myfile。

test=# \q
[pol@polhost inst]$ more myfile 
{"mary":2,"jimmy":43,"paulie":"asfasfasfd"}
{"mary":3,"jimmy":435,"paulie":"ererere"}
{"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}
[pol@polhost inst]$

(您可以尝试从

COPY (SELECT ROW_TO_JSON(t, TRUE)  -- <-- Note addition of "TRUE" here!

在您的闲暇时间)。

@ offby1指出输出(虽然对应于OP的问题)不正确JSON。@EvanCarroll指出,这\o也是一种输出到文件的方式,因此我在此语句中结合了这两个小问题的解决方案(在here的帮助下):

test=# \o out.json
test=# SELECT array_to_json(array_agg(fred), FALSE) AS ok_json FROM fred;
                                     -- <-- "TRUE" here will produce plus
                                        ("+) signs in the output. "FALSE"
                                        is the default anyway.
test=# \o

给出:

[pol@polhost inst]$ more out.json 
                                                                   ok_json                                                                    
----------------------------------------------------------------------------------------------------------------------------------------------
 [{"mary":2,"jimmy":43,"paulie":"asfasfasfd"},{"mary":3,"jimmy":435,"paulie":"ererere"},{"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}]
(1 row)
[pol@polhost inst]$ 

最后\@ AdamGent在他的帖子中提到了反斜杠()问题。这有点棘手,但是可能不诉诸查询后处理。Voilà:

INSERT INTO fred VALUES (35, 5, 'wrew\sdfsd');
INSERT INTO fred VALUES (3, 44545, '\sdfs\\\sfs\\gf');

并因此使用REGEXP_REPLACE(请注意强制转换:: TEXT)可删除多余的黑斜杠。

test=# \o slash.json
test=# SELECT REGEXP_REPLACE(ROW_TO_JSON(t)::TEXT, '\\\\', '\\', 'g') 
test=# FROM (SELECT * FROM fred) AS t;  -- I found that using a CTE was helpful for legibility
test=# \o
test=# \q

给出:

[pol@polhost inst]$ more slash.json 
                    regexp_replace                    
------------------------------------------------------
 {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}
 {"mary":3,"jimmy":435,"paulie":"ererere"}
 {"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}
 {"mary":35,"jimmy":5,"paulie":"wrew\sdfsd"}
 {"mary":3,"jimmy":44545,"paulie":"\sdfs\\\sfs\\gf"}
(5 rows)
[pol@polhost inst]$ 

(ps @Zoltán的评论-这可能是版本问题-无法复制!)。


2
这似乎正是原始海报想要的。但是请注意,尽管每都是正确的JSON,但行的集合却不是,因为它缺少逗号分隔行和包围行的方括号。
2016年

3
,如果你有任何的工作backslash在你列!!!! 请仔细阅读COPY文档,因为它对backslash字符有特殊作用(例如添加另一个反斜杠)。
亚当·根特

阅读以下@AdamGent的答案以解决反斜杠问题
FacePalm '17

1
所以... 2017年,没有办法使用COPY命令PostgreSQL 导出JSON?有CSV选项,TXT选项...为什么没有JSON选项?
彼得·克劳斯

1
谢谢@Vérace。抱歉,现在我使用复杂的JSONb测试了COPY,并且处理的JSON很好,“正确的JSON”!
彼得·克劳斯

13

如果您正在使用,psql则根本没有理由使用\COPY

\t
\a
\o file.json
SELECT row_to_json(r) FROM my_table AS r;

这与我们使用PostGIS将png / jpgs / tifs从数据库中取出进行快速测试,以及使用PostgreSQL扩展生成脚本文件时所使用的方法相同。


大!像通常的COPY命令“不允许相对路径”一样psql-native-commands是复制到相对路径最简单方法!PS:有一种“终端方式”可以使用带有相对路径的实际COPY命令,请参见此处psql -h remotehost -d remote_mydb -U myuser -c "COPY (SELECT '{\"x\":1,\"y\":[\"a\",2]}'::json AS r) TO STDOUT" > ./relative_path/file.csv
彼得·克劳斯

6

对我来说,@Vérace的回答并没有保持的列名,但分配默认名称(f1f2,等)来代替。我正在使用JSON扩展的 PostgreSQL 9.1 。

如果要导出整个表,则不需要子查询。此外,这保留列名。我使用以下查询:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';

它确实维护了列名!CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));其结果:{"mary":2,"jimmy":43,"paulie":"asfasfasfd"}-字段名是玛丽,吉米,保利...和NOTf1f2,等)...
Vérace

5

我将对Verace的回答特别说明如果您有带有反斜杠字符的文本列,则需要对输出的JSON文件进行后处理\

否则,您最多将得到重复(\-> \\),而更糟的是将完全无效的JSON即:

这个:

{ "f1" : "crap\""}.

成为

{ "f1" : "crap\\""}.

看起来不错,但完全无效的JSON。

您可以将sed 替换\\\sed:

sed -i -e 's/\\\\/\\/g' PG_OUT_JSON_FILE.json

他们在Postgres COPY的讨论中提到:

目前,COPY TO将永远不会发出八进制或十六进制的反斜杠序列,但它确实将上面列出的其他序列用于这些控制字符。上表中未提及的任何其他反斜杠字符都将代表其自身。但是,请注意不要不必要地添加反斜杠,因为这可能会意外地产生与数据结尾标记(。)或空字符串(默认为\ N)匹配的字符串。在完成任何其他反斜杠处理之前,将识别这些字符串。

强烈建议生成COPY数据的应用程序将数据换行符和回车符分别转换为\ n和\ r序列。目前,可以通过反斜杠和回车符来表示数据回车,并且可以通过反斜杠和换行符来表示数据换行。但是,将来的发行版中可能不接受这些表示。如果COPY文件在不同的计算机上传输(例如,从Unix到Windows,反之亦然),它们也极易受到破坏。

COPY TO将以Unix样式的换行符(“ \ n”)终止每一行。在Microsoft Windows上运行的服务器将输出回车符/换行符(“ \ r \ n”),但仅用于将COPY复制到服务器文件;为了实现跨平台的一致性,无论服务器平台如何,COPY TO STDOUT始终发送“ \ n”。COPY FROM可以处理以换行符,回车符或回车符/换行符结尾的行。为了减少由于未加反斜杠的换行符或将回车符作为数据而导致的错误风险,如果输入中的行尾并不完全相同,则COPY FROM将发出投诉。


我已经在回答中解决了这一问题-希望您觉得满意。如果没有,请告诉我。
Vérace


0

这是输出有效JSON(对象数组)的唯一方法。

\t
\a
\o data.json
select json_agg(t) FROM (SELECT * from table) t;

来源

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.