Exportar tabla de Postgres como json

35

¿Hay alguna manera de exportar datos de la tabla postgres como json a un archivo? Necesito que la salida sea línea por línea, como:

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

EDITAR: versión de postgres: 9.3.4

AliBZ
fuente

Respuestas:

48

Pruebe aquí para una introducción básica a PostgreSQLy JSON.

Además, la documentación de PostgreSQL es bastante buena, así que pruébelo aquí . Mira la pretty_boolopción.

Su pregunta original era "¿Hay alguna manera de exportar datos de la tabla de postgres como JSON". Lo querías en este formato

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

No tenía una instancia en ejecución de, PostgreSQLasí que descargué, compilé e instalé 9.4.

Para responder esto, primero CREATEedité una tabla (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');

Luego, para verificar:

test=# select * from fred;

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

Entonces emití 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=# 

Luego salí de psql y enumeré el archivo 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]$

(puede experimentar con la salida de

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

en su tiempo libre).

@ Offby1 señaló que la salida (aunque corresponde a la pregunta del OP) no es correcta JSON. @EvanCarroll señaló que \otambién es una forma de enviar a un archivo, por lo que combiné las soluciones a estos dos inconvenientes en esta declaración (con ayuda de aquí ):

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

da:

[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 , existe el \problema de la barra invertida ( ) aludido por @AdamGent en su publicación. Esto fue un poco complicado, pero es posible sin recurrir al procesamiento posterior a la consulta. Voilà:

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

Y al usar REGEXP_REPLACE de este modo (tenga en cuenta que cast :: TEXT) elimina el exceso de barras negras.

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

da:

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

(PD: En cuanto al comentario de @ Zoltán, esto puede ser una versión, ¡no se puede reproducir!).

Vérace
fuente
2
Eso parece ser exactamente lo que quería el póster original. Sin embargo, tenga en cuenta que si bien cada fila es JSON adecuada, la colección de filas no lo es, ya que carece de comas que separen las filas y corchetes que las rodean.
offby1
3
¡Esto NO funcionará si tiene alguno backslashen sus columnas! Lea atentamente el documento COPY, ya que hace cosas especiales para los backslashcaracteres (como agregar otra barra invertida).
Adam Gent
LEA la respuesta de @AdamGent a continuación para resolver el problema de la barra invertida
FacePalm
1
Entonces ... ¿año 2017 y NO MANERA DE EXPORTAR JSON con el comando COPY PostgreSQL? Hay opción CSV, opción TXT ... ¿Por qué no una opción JSON?
Peter Krauss el
1
Gracias @ Vérace. Y lo siento, ahora probé una COPIA con JSONb complejo y el JSON procedió estaba bien, "JSON correcto".
Peter Krauss el
13

Si está usando, psqlentonces no hay ninguna razón para usar \COPY.

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

Este es el mismo método que usamos para sacar png / jpgs / tifs de la base de datos con PostGIS para pruebas rápidas, y también para generar archivos de script con extensiones PostgreSQL.

Evan Carroll
fuente
¡Excelente! Como el comando COPY "no permite la ruta relativa" , los psqlcomandos nativos son la forma más fácil de copiar en la ruta relativa . PD: hay una "forma terminal" para usar el comando COPY real con ruta relativa, ver aquí . 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 el
6

Para mí la respuesta de @ Verace no mantuvo los nombres de las columnas, pero los nombres predeterminados asignados ( f1, f2, etc.) en su lugar. Estoy usando PostgreSQL 9.1 con la extensión JSON .

Si desea exportar toda la tabla, no hay necesidad de una subconsulta. Además, este será mantener los nombres de columna. Usé la siguiente consulta:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';
Zoltán
fuente
¡Mantuvo los nombres de columna! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));y el resultado: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- nombres de campo son María, barreta, Paulie ... y NO ( f1, f2., etc) ...
Verace
5

Agregaré una advertencia especial a la respuesta de Verace . Que tiene que hacer el procesamiento posterior en el archivo JSON emitida si tiene columnas de texto con caracteres de barra invertida:\ .

De lo contrario, obtendrá duplicados ( \-> \\) en el mejor de los casos y JSON completamente inválido en el peor, es decir:

Esta:

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

Se convierte

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

Que se ve bien pero es completamente inválido JSON.

Puede reemplazar el \\en \con sed:

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

De Postgres COPY donde redondean mencionarlo:

Actualmente, COPY TO nunca emitirá una secuencia de barra invertida octal o de dígitos hexadecimales, pero sí utiliza las otras secuencias enumeradas anteriormente para esos caracteres de control. Cualquier otro carácter de barra invertida que no se mencione en la tabla anterior se considerará que se representa a sí mismo. Sin embargo, tenga cuidado de agregar barras invertidas innecesariamente, ya que eso podría producir accidentalmente una cadena que coincida con el marcador de fin de datos (.) O la cadena nula (\ N por defecto). Estas cadenas se reconocerán antes de que se realice cualquier otro procesamiento de barra diagonal inversa.

Se recomienda encarecidamente que las aplicaciones que generan datos COPY conviertan las nuevas líneas de datos y los retornos de carro en las secuencias \ n y \ r respectivamente. En la actualidad, es posible representar un retorno de carro de datos mediante una barra diagonal inversa y un retorno de carro, y representar una nueva línea de datos mediante una barra diagonal inversa y una nueva línea. Sin embargo, estas representaciones pueden no ser aceptadas en futuras versiones. También son muy vulnerables a la corrupción si el archivo COPY se transfiere a través de diferentes máquinas (por ejemplo, desde Unix a Windows o viceversa).

COPY TO terminará cada fila con una nueva línea de estilo Unix ("\ n"). En cambio, los servidores que se ejecutan en Microsoft Windows generan retorno de carro / nueva línea ("\ r \ n"), pero solo para COPIAR a un archivo de servidor; para mantener la coherencia entre plataformas, COPY TO STDOUT siempre envía "\ n" independientemente de la plataforma del servidor. COPY FROM puede manejar líneas que terminan con líneas nuevas, retornos de carro o retorno de carro / líneas nuevas. Para reducir el riesgo de error debido a nuevas líneas sin recortar o retornos de carro que se entendieron como datos, COPY FROM se quejará si las terminaciones de línea en la entrada no son todas iguales.

Adam Gent
fuente
He tratado con este en la respuesta, espero que lo encuentre satisfactorio. Si no, házmelo saber.
Vérace
1

Para obtener una solución genérica (MySQL, Postgres, SQLite ...) y gratuita para la que no tiene que instalar ningún software (excepto Docker), consulte https://github.com/function61/sql2json

Divulgación completa: escribí ese software.

joonas.fi
fuente
0

Este es el único método que genera JSON (matriz de objetos) válidos .

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

( fuente )

Gunar Gessner
fuente