web-dev-qa-db-fra.com

Comment importer un fichier JSON dans PostgreSQL?

Par exemple, j'ai un fichier customers.json qui est un tableau d'objets (strictement formé) et qui est assez simple (sans objets imbriqués) comme celui-ci (ce qui est important: il inclut déjà les identifiants):

[
  {
    "id": 23635,
    "name": "Jerry Green",
    "comment": "Imported from facebook."
  },
  {
    "id": 23636,
    "name": "John Wayne",
    "comment": "Imported from facebook."
  }
]

Et je veux les importer tous dans ma base de données postgres dans une table customers.

J'ai trouvé des moyens assez difficiles quand je devais l'importer en tant que colonne de type json dans une table comme imported_json et une colonne nommée data avec les objets qui y sont répertoriés, puis utiliser sql pour obtenir ces valeurs et les insérer dans une vraie table.

Mais existe-t-il un moyen simple d'importer json dans postgres sans toucher à sql?

18
Jerry Green

Vous pouvez alimenter le JSON dans une instruction SQL qui extrait les informations et les insère dans la table. Si les attributs JSON ont exactement le nom comme colonnes de table, vous pouvez faire quelque chose comme ceci:

with customer_json (doc) as (
   values 
    ('[
      {
        "id": 23635,
        "name": "Jerry Green",
        "comment": "Imported from facebook."
      },
      {
        "id": 23636,
        "name": "John Wayne",
        "comment": "Imported from facebook."
      }
    ]'::json)
)
insert into customer (id, name, comment)
select p.*
from customer_json l
  cross join lateral json_populate_recordset(null::customer, doc) as p
on conflict (id) do update 
  set name = excluded.name, 
      comment = excluded.comment;

De nouveaux clients seront insérés, les clients existants seront mis à jour. La partie "magique" est la json_populate_recordset(null::customer, doc) qui génère une représentation relationnelle des objets JSON.


Ce qui précède suppose une définition de table comme celle-ci:

create table customer 
(
  id        integer primary key,
  name      text not null,
  comment   text
);

Si les données sont fournies sous forme de fichier, vous devez d'abord placer ce fichier dans une table de la base de données. Quelque chose comme ça:

create unlogged table customer_import (doc json);

Téléchargez ensuite le fichier sur une seule ligne de ce tableau, par ex. en utilisant la commande \copy dans psql (ou tout ce que propose votre client SQL):

\copy customer_import from 'customers.json' ....

Ensuite, vous pouvez utiliser l'instruction ci-dessus, supprimez simplement le CTE et utilisez la table de transfert:

insert into customer (id, name, comment)
select p.*
from customer_import l
  cross join lateral json_populate_recordset(null::customer, doc) as p
on conflict (id) do update 
  set name = excluded.name, 
      comment = excluded.comment;
28

Il s'avère qu'il existe un moyen facile d'importer un objet JSON multiligne dans une colonne JSON dans une base de données postgres à l'aide de l'outil psql en ligne de commande, sans avoir besoin d'incorporer explicitement le JSON dans l'instruction SQL. La technique est documentée dans le postgresql docs , mais elle est un peu cachée.

L'astuce consiste à charger le JSON dans une variable psql à l'aide de backticks. Par exemple, étant donné un fichier JSON à plusieurs lignes dans /tmp/test.json tel que:

{
  "dog": "cat",
  "frog": "frat"
}

Nous pouvons utiliser le SQL suivant pour le charger dans une table temporaire:

sql> \set content `cat /tmp/test.json`
sql> create temp table t ( j jsonb );
sql> insert into t values (:'content');
sql> select * from t;

ce qui donne le résultat:

               j                
────────────────────────────────
 {"dog": "cat", "frog": "frat"}
(1 row)

Vous pouvez également effectuer des opérations sur les données directement:

sql> select :'content'::jsonb -> 'dog';
 ?column? 
──────────
 "cat"
(1 row)

Sous les couvertures, ceci est juste en incorporant le JSON dans le SQL, mais c'est beaucoup plus net de laisser psql effectuer l'interpolation lui-même.

25
Doctor Eval

Le moyen le plus simple d'importer json à partir d'un fichier semble ne pas importer un seul json à partir d'un fichier mais plutôt une seule colonne csv: une liste de jsons d'une ligne:

data.json:

{"id": 23635,"name": "Jerry Green","comment": "Imported from facebook."}
{"id": 23636,"name": "John Wayne","comment": "Imported from facebook."}

puis, sous psql:

create table t ( j jsonb )
\copy t from 'd:\path\data.json'

Un enregistrement par json (ligne) sera ajouté dans la table t.

L'importation "\ copy from" a été effectuée pour csv et charge ainsi les données ligne par ligne. Par conséquent, la lecture d'un json par ligne plutôt que d'un seul tableau json à fractionner ultérieurement, n'utilisera aucune table intermédiaire.

De plus, vous n'atteindrez pas la limitation maximale de la taille de la ligne d'entrée qui se déclenchera si votre fichier json d'entrée est trop volumineux.

Je voudrais donc d'abord convertir votre entrée en une seule colonne csv pour ensuite l'importer en utilisant la commande copy.

2
user1767316