Exportar tabela do Postgres como json

35

Existe uma maneira de exportar dados da tabela do postgres como json para um arquivo? Eu preciso que a saída seja linha por linha, como:

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

EDIT: versão do postgres: 9.3.4

AliBZ
fonte

Respostas:

48

Tente aqui para obter uma introdução básica a PostgreSQLe JSON.

Além disso, a documentação do PostgreSQL é muito boa, então tente aqui . Confira a pretty_boolopção.

Sua pergunta original era "Existe uma maneira de exportar os dados da tabela do postgres como JSON". Você queria neste formato

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

Eu não tinha uma instância em execução, PostgreSQLentão baixei, compilei e instalei a 9.4.

Para responder a isso, CREATEeditei uma tabela (fred)

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');

Então, para verificar:

test=# select * from fred;

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

Então eu emiti este comando

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

Então, fechei o psql e listei o arquivo 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]$

(você pode experimentar a saída de

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

quando quiser).

Foi apontado por @ offby1 que a saída (embora corresponda à pergunta do OP) não está correta JSON. O @EvanCarroll apontou que \otambém é uma maneira de gerar um arquivo, então eu combinei as soluções para essas duas imperfeições nesta declaração (com a ajuda daqui ):

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

dá:

[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]$ 

Finalmente , há o \problema de barra invertida ( ) mencionado por @AdamGent em seu post. Isso foi um pouco complicado, mas é possível sem recorrer ao processamento pós-consulta. Voilà:

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

E usar REGEXP_REPLACE assim (observe o cast :: TEXT) remove as barras negras em excesso.

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

dá:

[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 Quanto ao comentário de @ Zoltán - isso pode ser uma versão - não é possível reproduzir!).

Vérace
fonte
2
Isso parece ser exatamente o que o pôster original queria. Observe, no entanto, que, embora cada linha seja JSON adequada, a coleção de linhas não é, pois falta vírgulas separando as linhas e colchetes ao seu redor.
usar o seguinte comando
3
Isso NÃO funcionará se você tiver algum backslashem suas colunas !!!! Leia atentamente o documento COPY, pois ele faz coisas especiais para os backslashcaracteres (como adicionar outra barra invertida).
Adam Gent
Leia a resposta de @AdamGent abaixo para resolver o problema de barra invertida #
FacePalm
11
Então ... ano de 2017 e NENHUMA MANEIRA DE EXPORTAR JSON com o comando COPY PostgreSQL ?? Há opção CSV, opção TXT ... Por que não uma opção JSON?
Peter Krauss
11
Obrigado @ Vérace. E desculpe, agora testei uma CÓPIA com JSONb complexo e o JSON processado estava bom, "JSON adequado"!
Peter Krauss
13

Se você estiver usando psql, não há motivo para usá \COPY-lo.

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

Este é o mesmo método que usamos para obter png / jpgs / tifs do banco de dados com o PostGIS para testes rápidos e também para gerar arquivos de script com extensões do PostgreSQL.

Evan Carroll
fonte
Ótimo! Como o comando COPY usual "não permite o caminho relativo" , os psqlcomandos -native-é a maneira mais fácil de copiar para o caminho relativo ! PS: existe uma "maneira terminal" de usar o comando COPY real com caminho relativo, veja aqui . 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
Peter Krauss
6

Para mim @ resposta de Verace não manteve os nomes das colunas, mas os nomes padrão atribuídos ( f1, f2, etc.) em vez. Estou usando o PostgreSQL 9.1 com a extensão JSON .

Se você deseja exportar a tabela inteira, não há necessidade de uma subconsulta. Além disso, este irá manter os nomes das colunas. Eu usei a seguinte consulta:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';
Zoltán
fonte
Manteve os nomes das colunas! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));eo resultado: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- nomes dos campos são mary, jimmy, Paulie ... e NÃO ( f1, f2., etc) ...
Verace
5

Vou acrescentar uma advertência especial à resposta de Verace . Você precisa fazer o pós-processamento no arquivo JSON transmitido se você tem colunas de texto com caracteres de barra invertida:\ .

Caso contrário, você será duplicado ( \-> \\) na melhor das hipóteses e completamente inválido no JSON na pior, ou seja:

Este:

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

Torna-se

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

O que parece bom, mas é um JSON completamente inválido.

Você pode substituir o \\into \pelo sed:

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

Do Postgres COPY, onde eles mencionam:

Atualmente, COPY TO nunca emitirá uma seqüência de barras invertidas octal ou hexadecimal, mas usa as outras seqüências listadas acima para esses caracteres de controle. Qualquer outro caractere barra invertida que não seja mencionado na tabela acima será usado para representar a si mesmo. No entanto, tenha cuidado ao adicionar barras invertidas desnecessariamente, pois isso pode produzir acidentalmente uma cadeia de caracteres correspondente ao marcador de fim de dados (.) Ou a cadeia de caracteres nula (\ N por padrão). Essas seqüências serão reconhecidas antes de qualquer outro processamento de barra invertida.

É altamente recomendável que aplicativos que geram dados COPY convertam novas linhas de dados e retornos de carro nas seqüências \ n e \ r, respectivamente. Atualmente, é possível representar um retorno de carro de dados por uma barra invertida e retorno de carro, e representar uma nova linha de dados por uma barra invertida e nova linha. No entanto, essas representações podem não ser aceitas em versões futuras. Eles também são altamente vulneráveis ​​à corrupção se o arquivo COPY for transferido por máquinas diferentes (por exemplo, do Unix para o Windows ou vice-versa).

COPY TO terminará cada linha com uma nova linha no estilo Unix ("\ n"). Os servidores em execução no Microsoft Windows produzem retorno de carro / nova linha ("\ r \ n"), mas apenas para COPY em um arquivo do servidor; para consistência entre as plataformas, o COPY TO STDOUT sempre envia "\ n" independentemente da plataforma do servidor. COPY FROM pode lidar com linhas que terminam com novas linhas, retornos de carro ou retorno de carro / novas linhas. Para reduzir o risco de erro devido a novas linhas sem barra invertida ou retornos de carro que foram concebidos como dados, COPY FROM reclamará se as terminações de linha na entrada não forem todas iguais.

Adam Gent
fonte
Eu lidei com este na resposta - espero que você o satisfaça. Se não, me avise.
Vérace 9/09
1

Para uma solução genérica (MySQL, Postgres, SQLite ..) e gratuita para a qual você não precisa instalar nenhum software (exceto o Docker), consulte https://github.com/function61/sql2json

Divulgação completa: eu escrevi esse software.

joonas.fi
fonte
0

Este é o único método que gera JSON (matriz de objetos) válido .

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

( fonte )

Gunar Gessner
fonte