Esporta la tabella Postgres come json


35

C'è un modo per esportare i dati della tabella di Postgres come json in un file? Ho bisogno che l'output sia riga per riga, come:

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

EDIT: versione postgres: 9.3.4

Risposte:


48

Prova qui per un'introduzione di base a PostgreSQLe JSON.

Inoltre, la documentazione di PostgreSQL è piuttosto buona, quindi provala qui . Dai un'occhiata pretty_boolall'opzione.

La tua domanda originale era "Esiste un modo per esportare i dati della tabella postgres come JSON". Lo volevi in ​​questo formato

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

Non avevo un'istanza in esecuzione, PostgreSQLquindi ho scaricato, compilato e installato 9.4.

Per rispondere a questo, ho prima CREATEredatto un tavolo (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');

Quindi, per controllare:

test=# select * from fred;

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

Quindi ho emesso questo 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=# 

Ho quindi chiuso psql ed elencato il file 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]$

(puoi provare l'output di

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

a vostro piacimento).

È stato sottolineato da @ offby1 che l'output (sebbene corrisponda alla domanda del PO) non è corretto JSON. @EvanCarroll ha sottolineato che \oè anche un modo per inviare a un file, quindi ho combinato le soluzioni a questi due nervi in ​​questa affermazione (con l'aiuto di qui ):

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 , c'è il \problema backslash ( ) a cui allude @AdamGent nel suo post. Questo è stato un po 'complicato, ma è possibile senza ricorrere all'elaborazione post-query. Ecco:

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

E l'utilizzo di REGEXP_REPLACE in questo modo (notare il cast :: TEXT) rimuove le ciglia nere in eccesso.

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 Per quanto riguarda il commento di @Zoltán - questa potrebbe essere una cosa versione - incapace di riprodurre!).


2
Questo sembra essere esattamente ciò che voleva il poster originale. Si noti, tuttavia, che mentre ogni riga è corretta JSON, la raccolta di righe non lo è, poiché manca di virgole che separano le righe e parentesi quadre che le circondano.
off1,

3
Questo NON funzionerà se ne hai uno backslashnelle tue colonne !!!! Leggi attentamente il documento COPIA poiché fa cose speciali per i backslashpersonaggi (come aggiungere un'altra barra rovesciata).
Adam Gent,

LEGGI la risposta di @AdamGent di seguito per risolvere il problema della barra rovesciata
FacePalm,

1
Quindi ... anno 2017 e NESSUN MODO DI ESPORTARE JSON con il comando COPY PostgreSQL ?? Ci sono l'opzione CSV, l'opzione TXT ... Perché non un'opzione JSON?
Peter Krauss,

1
Grazie @ Verace. E scusa, ora ho provato una COPIA con JSONb complessi e il JSON proceduto andava bene, "JSON corretto"!
Peter Krauss,

13

Se stai usando, psqlnon c'è motivo di usarlo \COPYaffatto.

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

Questo è lo stesso metodo che usiamo per estrarre png / jpgs / tifs dal database con PostGIS per test rapidi e anche per generare file di script con estensioni PostgreSQL.


Grande! Come al solito comando COPIA "non consentire il percorso relativo" , i psqlcomandi -native sono il modo più semplice per copiare nel percorso relativo ! PS: esiste un "modo terminale" per usare il vero comando COPIA con relativo percorso, vedi qui . 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

Per me la risposta di @ Verace non ha mantenuto i nomi delle colonne, ma i nomi predefiniti assegnati ( f1, f2, ecc), invece. Sto usando PostgreSQL 9.1 con l' estensione JSON .

Se si desidera esportare l'intera tabella, non è necessario un subquery. Inoltre, questo sarà mantenere i nomi delle colonne. Ho usato la query folowing:

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

Ha mantenuto i nomi delle colonne! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));e il risultato: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- i nomi dei campi sono Mary, jimmy, Paulie ... e non ( f1, f2., ecc) ...
Verace

5

Aggiungerò un avvertimento speciale alla risposta di Verace . Hai bisogno di fare post processing sul file JSON emesso se si dispone di colonne di testo con caratteri di barra rovesciata:\ .

Altrimenti otterrai duplicati ( \-> \\) nel migliore dei casi e JSON completamente non valido nel peggiore dei casi, ad esempio:

Questo:

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

diventa

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

Che sembra a posto ma non è completamente valido JSON.

È possibile sostituire il \\in \con sed:

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

Da Postgres COPY dove si girano per menzionarlo:

Attualmente, COPY TO non emetterà mai una sequenza di barre rovesciate ottali o di cifre esadecimali, ma utilizza le altre sequenze sopra elencate per quei caratteri di controllo. Qualsiasi altro carattere rovesciato che non è menzionato nella tabella sopra verrà preso per rappresentare se stesso. Tuttavia, attenzione ad aggiungere inutilmente le barre rovesciate, poiché ciò potrebbe produrre accidentalmente una stringa corrispondente al marker di fine dati (.) O alla stringa null (\ N per impostazione predefinita). Queste stringhe verranno riconosciute prima di qualsiasi altra elaborazione backslash.

Si consiglia vivamente che le applicazioni che generano dati COPY convertano i dati di nuova riga e i ritorni a capo rispettivamente nelle sequenze \ n e \ r. Al momento è possibile rappresentare un ritorno a capo di dati da una barra rovesciata e un ritorno a capo e rappresentare una linea di dati nuova da una barra rovesciata e una linea nuova. Tuttavia, queste rappresentazioni potrebbero non essere accettate nelle versioni future. Sono anche altamente vulnerabili alla corruzione se il file COPY viene trasferito su macchine diverse (ad esempio, da Unix a Windows o viceversa).

COPIA A terminerà ogni riga con una nuova riga in stile Unix ("\ n"). I server in esecuzione su Microsoft Windows invece restituiscono il ritorno a capo / newline ("\ r \ n"), ma solo per COPIA su un file server; per coerenza tra le piattaforme, COPY TO STDOUT invia sempre "\ n" indipendentemente dalla piattaforma server. COPIA DA può gestire le linee che terminano con nuove righe, ritorni a capo o ritorno a capo / nuovi. Per ridurre il rischio di errore a causa di newline non rovesciate o di ritorni a capo che erano intesi come dati, COPY FROM si lamenterà se le terminazioni di riga nell'input non sono tutte uguali.


Ho risolto questo problema nella risposta: spero che lo troviate soddisfacente. In caso contrario, fammi sapere.
Vérace,


0

Questo è l'unico metodo che ha prodotto JSON (array di oggetti) valido .

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

( fonte )

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.