Exporter la table Postgres en json

35

Existe-t-il un moyen d’exporter les données de la table postgres au format json dans un fichier? J'ai besoin que la sortie soit ligne par ligne, comme:

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

EDIT: version postgres: 9.3.4

AliBZ
la source

Réponses:

48

Essayez ici pour une introduction de base à PostgreSQLet JSON.

De plus, la documentation PostgreSQL est assez bonne, essayez-la ici . Découvrez l' pretty_booloption.

Votre question initiale était "Y at-il un moyen d’exporter les données de la table postgres en tant que JSON". Vous l'avez voulu dans ce format

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

Je n'avais pas d'instance en cours d'exécution PostgreSQL, j'ai donc téléchargé, compilé et installé la version 9.4.

Pour répondre à cela, j'ai d'abord CREATEédité un tableau (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');

Ensuite, pour vérifier:

test=# select * from fred;

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

Puis j'ai émis cette commande

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

J'ai alors quitté psql et répertorié le fichier 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]$

(vous pouvez expérimenter avec la sortie de

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

à votre guise).

@ Offby1 a souligné que la sortie (bien qu'elle corresponde à la question du PO) n'est pas correcte JSON. @EvanCarroll a souligné que c'était \oaussi un moyen de sortir dans un fichier, alors j'ai combiné les solutions à ces deux problèmes dans cette déclaration (avec l'aide de ):

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

donne:

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

ENFIN , il y a le \problème de backslash ( ) mentionné par @AdamGent dans son post. Ce fut un peu difficile, mais il est possible sans avoir recours à un traitement post-requête. Voilà:

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

Et en utilisant REGEXP_REPLACE ainsi (notez la fonte :: TEXT) supprime les barres noires en excès.

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

donne:

[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 Quant au commentaire de @ Zoltán - cela peut être une version - impossible à reproduire!).

Vérace
la source
2
Cela semble être exactement ce que l'affiche originale voulait. Notez cependant que, même si chaque ligne correspond à JSON, la collection de lignes ne l’est pas, car il manque les virgules séparant les lignes et les crochets qui les entourent.
offby1
3
Cela ne fonctionnera PAS si vous en avez backslashdans vos colonnes !!!! Lisez attentivement le document COPY car il fait des choses spéciales pour les backslashcaractères (comme l’ajout d’une autre barre oblique inverse).
Adam Gent
LIRE la réponse de @AdamGent ci-dessous pour résoudre le problème de la barre oblique inversée
FacePalm
1
Donc ... année 2017 et NO WAY EXPORT JSON avec la commande COPY PostgreSQL ?? Il existe des options CSV, TXT ... Pourquoi pas une option JSON?
Peter Krauss
1
Merci @ Vérace. Et désolé, maintenant j'ai testé une copie avec le JSONb complexe et le JSON traité était bon, "bon JSON"!
Peter Krauss
13

Si vous utilisez, psqlil n'y a aucune raison d'utiliser \COPYdu tout.

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

C'est la même méthode que nous utilisons pour extraire les fichiers png / jpgs / tifs de la base de données avec PostGIS pour des tests rapides, ainsi que pour générer des fichiers de script avec des extensions PostgreSQL.

Evan Carroll
la source
Génial! Comme d'habitude la commande COPY "ne pas autoriser le chemin relatif" , les psqlcommandes -natives sont le moyen le plus simple de copier dans le chemin relatif ! PS: il existe un "moyen terminal" pour utiliser une commande COPY réelle avec un chemin relatif, voir ici . 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

Pour moi @ La réponse de Verace n'a pas conservé les noms de colonnes, mais les noms par défaut attribués ( f1, f2, etc.) à la place. J'utilise PostgreSQL 9.1 avec l' extension JSON .

Si vous souhaitez exporter l'intégralité de la table, une sous-requête n'est pas nécessaire. De plus, cela va maintenir les noms de colonnes. J'ai utilisé la requête suivante:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';
Zoltán
la source
Il a maintenu les noms de colonne! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));et le résultat: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- les noms de champs sont mary, jimmy, Paulie ... et pas ( f1, f2., etc) ...
Verace
5

J'ajouterai une mise en garde spéciale à la réponse de Verace . Vous devez faire le traitement post sur le fichier JSON si vous avez émis des colonnes de texte avec des caractères backslash:\ .

Sinon, vous obtiendrez au pire un duplicata ( \-> \\) et au pire un JSON invalide, par exemple:

Cette:

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

Devient

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

Ce qui semble bien mais est complètement invalide JSON.

Vous pouvez remplacer le \\en \avec sed:

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

De Postgres COPY où ils sont mentionnés:

À l’heure actuelle, COPY TO n’émettra jamais de séquence de barre oblique inversée à chiffres octaux ou hexadécimaux, mais il utilise les autres séquences répertoriées ci-dessus pour ces caractères de contrôle. Tout autre caractère anti-slash non mentionné dans le tableau ci-dessus sera considéré comme représentant lui-même. Cependant, méfiez-vous des ajouts inutiles de barres obliques inverses, car cela pourrait produire accidentellement une chaîne correspondant au marqueur de fin de données (.) Ou à la chaîne null (\ N par défaut). Ces chaînes seront reconnues avant tout autre traitement de barre oblique inverse.

Il est vivement recommandé aux applications générant des données COPY de convertir les nouvelles lignes et les retours à la ligne des séquences \ n et \ r respectivement. Il est actuellement possible de représenter un retour chariot de données par une barre oblique inversée et un retour chariot, et de représenter une nouvelle ligne de données par une barre oblique inverse et une nouvelle ligne. Cependant, ces représentations pourraient ne pas être acceptées dans les versions ultérieures. Ils sont également très vulnérables à la corruption si le fichier COPY est transféré sur différentes machines (par exemple, d'Unix à Windows ou vice versa).

COPY TO terminera chaque ligne par une nouvelle ligne de style Unix ("\ n"). Les serveurs fonctionnant sous Microsoft Windows génèrent plutôt un retour chariot / nouvelle ligne ("\ r \ n"), mais uniquement pour COPY dans un fichier serveur; Pour assurer la cohérence entre les plates-formes, COPY TO STDOUT envoie toujours "\ n" quelle que soit la plate-forme du serveur. COPY FROM peut gérer les lignes se terminant par des nouvelles lignes, des retours chariot ou des retours chariot / nouvelles lignes. Pour réduire le risque d'erreur due à des lignes nouvelles ou des retours à la ligne sans barres obliques inversées qui étaient supposées être des données, COPY FROM se plaindra si les fins de ligne de l'entrée ne sont pas toutes identiques.

Adam Gent
la source
J'ai traité celui-ci dans la réponse - j'espère que vous le trouverez satisfaisant. Si non, faites le moi savoir.
Vérace le
1

Pour obtenir une solution générique (MySQL, Postgres, SQLite ..) et gratuite pour laquelle vous ne devez installer aucun logiciel (à l'exception de Docker), voir https://github.com/function61/sql2json.

Divulgation complète: j'ai écrit ce logiciel.

joonas.fi
la source
0

Cette méthode est la seule à générer un JSON (tableau d’objets) valide .

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

( source )

Gunar Gessner
la source