Ekspor tabel Postgres sebagai json

35

Apakah ada cara untuk mengekspor data tabel postgres sebagai json ke file? Saya perlu output menjadi baris demi baris, seperti:

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

EDIT: versi postgres: 9.3.4

AliBZ
sumber

Jawaban:

48

Coba di sini untuk pengantar dasar ke PostgreSQLdan JSON.

Juga, dokumentasi PostgreSQL cukup bagus, jadi coba di sini . Lihat pretty_boolopsi.

Pertanyaan awal Anda adalah "Apakah ada cara untuk mengekspor data tabel postgres sebagai JSON". Anda menginginkannya dalam format ini

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

Saya tidak memiliki instance yang sedang berjalan PostgreSQLsehingga saya mengunduh, mengkompilasi dan menginstal 9.4.

Untuk menjawab ini, saya pertama-tama CREATEmengedit tabel (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');

Kemudian, untuk memeriksa:

test=# select * from fred;

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

Lalu saya mengeluarkan perintah ini

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

Saya kemudian berhenti psql dan daftar 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]$

(Anda dapat bereksperimen dengan output dari

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

di waktu luang Anda).

Itu ditunjukkan oleh @ offby1 bahwa output (sementara sesuai dengan pertanyaan OP) tidak benar JSON. @EvanCarroll menunjukkan bahwa \oini juga merupakan cara untuk menghasilkan file, jadi saya menggabungkan solusi untuk dua niggle ini dalam pernyataan ini (dengan bantuan dari sini ):

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

memberi:

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

AKHIRNYA , ada masalah backslash ( \) yang disinggung oleh @AdamGent dalam posnya. Ini adalah sedikit rumit, tetapi adalah mungkin tanpa menggunakan pengolahan pasca-query. Voa:

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

Dan dengan menggunakan REGEXP_REPLACE demikian (perhatikan gips :: TEXT) menghapus kelebihan blackslash.

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

memberi:

[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 As untuk komentar Zoltán - ini mungkin versi versi - tidak dapat direproduksi!).

Vérace
sumber
2
Tampaknya itulah yang diinginkan oleh poster aslinya. Perhatikan, bagaimanapun, bahwa meskipun setiap baris adalah JSON yang tepat, koleksi baris tidak, karena tidak memiliki koma yang memisahkan baris, dan tanda kurung siku yang mengelilinginya.
offby1
3
Ini TIDAK akan bekerja jika Anda punya backslashdi kolom Anda !!!! Baca dengan seksama dokumen COPY karena ia melakukan hal-hal khusus untuk backslashkarakter (seperti menambahkan backslash lain).
Adam Gent
BACA @AdamGent jawaban di bawah ini untuk menyelesaikan masalah backslash
FacePalm
1
Jadi ... tahun 2017 dan TIDAK CARA MENGEKSPOR JSON dengan perintah COPY PostgreSQL ?? Ada opsi CSV, opsi TXT ... Mengapa bukan opsi JSON?
Peter Krauss
1
Terima kasih @ Vérace. Dan maaf, sekarang saya menguji COPY dengan JSONb kompleks dan JSON yang diproses baik-baik saja, "JSON yang tepat"!
Peter Krauss
13

Jika Anda menggunakan psqlmaka tidak ada alasan untuk menggunakannya \COPYsama sekali.

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

Ini adalah metode yang sama yang kita gunakan untuk mengeluarkan png / jpgs / tif dari database dengan PostGIS untuk pengujian cepat, dan juga untuk menghasilkan file skrip dengan ekstensi PostgreSQL.

Evan Carroll
sumber
Besar! Seperti perintah COPY yang biasa "tidak mengizinkan jalur relatif" , psql-natif-perintah adalah cara termudah untuk menyalin ke jalur relatif ! PS: ada "cara terminal" untuk menggunakan perintah COPY nyata dengan jalur relatif, lihat di sini . 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

Bagi saya @ jawaban Verace ini tidak menjaga nama kolom, namun nama-nama standar yang ditetapkan ( f1, f2, dll) sebagai gantinya. Saya menggunakan PostgreSQL 9.1 dengan ekstensi JSON .

Jika Anda ingin mengekspor seluruh tabel, tidak perlu subquery. Selain itu, ini akan mempertahankan nama kolom. Saya menggunakan permintaan berikut:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';
Zoltán
sumber
Itu memang mempertahankan nama kolom! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));dan hasil: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- nama field yang mary, jimmy, Paulie ... dan TIDAK ( f1, f2., dll) ...
Verace
5

Saya akan menambahkan peringatan khusus untuk jawaban Verace . Anda perlu melakukan pengolahan pasca pada file JSON yang dikeluarkan jika Anda memiliki kolom teks dengan karakter backslash:\ .

Kalau tidak, Anda akan mendapatkan duplikat ( \-> \\) di JSON terbaik dan benar-benar tidak valid di lebih buruk yaitu:

Ini:

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

Menjadi

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

Yang terlihat baik-baik saja tetapi JSON benar-benar tidak valid.

Anda dapat mengganti \\ke \dengan sed:

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

Dari Postgres COPY di mana mereka sekitar menyebutkannya:

Saat ini, COPY TO tidak akan pernah memancarkan urutan garis miring terbalik oktal atau hex-digit, tetapi ia menggunakan urutan lain yang tercantum di atas untuk karakter kontrol tersebut. Karakter backslashed lainnya yang tidak disebutkan dalam tabel di atas akan dianggap mewakili dirinya sendiri. Namun, berhati-hatilah dalam menambahkan backslash yang tidak perlu, karena hal itu mungkin secara tidak sengaja menghasilkan string yang cocok dengan penanda akhir data (.) Atau string nol (\ N secara default). String ini akan dikenali sebelum pemrosesan backslash lainnya dilakukan.

Sangat disarankan bahwa aplikasi yang menghasilkan data COPY mengonversi baris baru data dan carriage return ke urutan masing-masing. Saat ini dimungkinkan untuk merepresentasikan carriage return data dengan backslash dan carriage return, dan untuk merepresentasikan data baris baru dengan backslash dan baris baru. Namun, representasi ini mungkin tidak diterima di rilis mendatang. Mereka juga sangat rentan terhadap korupsi jika file COPY ditransfer melalui mesin yang berbeda (misalnya, dari Unix ke Windows atau sebaliknya).

COPY TO akan mengakhiri setiap baris dengan baris gaya Unix ("\ n"). Server yang menjalankan Microsoft Windows sebagai gantinya menghasilkan carriage return / newline ("\ r \ n"), tetapi hanya untuk COPY ke file server; untuk konsistensi di seluruh platform, COPY TO STDOUT selalu mengirim "\ n" terlepas dari platform server. COPY FROM dapat menangani garis yang diakhiri dengan baris baru, carriage return, atau carriage return / newlines. Untuk mengurangi risiko kesalahan karena baris baru yang tidak di-backslash atau carriage return yang dimaksudkan sebagai data, COPY FROM akan mengeluh jika garis yang diakhiri pada input tidak semuanya sama.

Adam Gent
sumber
Saya telah membahas jawaban ini - saya harap Anda merasa ini memuaskan. Jika tidak, beri tahu saya.
Vérace
1

Untuk solusi generik (MySQL, Postgres, SQLite ..) dan gratis yang Anda tidak perlu menginstal perangkat lunak apa pun untuk (kecuali Docker), lihat https://github.com/function61/sql2json

Pengungkapan penuh: Saya menulis perangkat lunak itu.

joonas.fi
sumber
0

Ini adalah satu-satunya metode yang menampilkan JSON (array objek) yang valid .

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

( sumber )

Gunar Gessner
sumber