Import et export JSONL vers bases de données : PostgreSQL, MongoDB et plus
Un guide complet pour importer des fichiers JSONL dans des bases de données et exporter des enregistrements de base de données en JSONL. Couvre les commandes COPY de PostgreSQL, les outils CLI de MongoDB, JSON_TABLE de MySQL, les scripts SQLite et les patterns d’import en masse prêts pour la production.
Dernière mise à jour : février 2026
Pourquoi utiliser JSONL pour l’import et l’export de bases de données ?
JSONL (JSON Lines) est devenu un format privilégié pour déplacer des données entre bases de données et systèmes externes. Chaque ligne est un objet JSON indépendant et autonome, ce qui signifie que vous pouvez streamer les enregistrements un par un sans charger l’ensemble du jeu de données en mémoire. C’est essentiel lorsque vous migrez des millions de lignes entre instances PostgreSQL, synchronisez des collections MongoDB vers un entrepôt de données ou alimentez des exports de base de données dans des pipelines de machine learning.
Comparé au CSV, JSONL préserve les types de données, prend en charge les objets imbriqués et les tableaux, et élimine l’ambiguïté de l’échappement des délimiteurs. Un fichier JSONL peut transporter une colonne PostgreSQL jsonb telle quelle, alors que le CSV nécessiterait d’aplatir ou d’échapper la structure imbriquée. Comparé à un tableau JSON complet, JSONL est streamable : vous pouvez traiter, valider ou transformer chaque enregistrement au moment de sa lecture, plutôt que d’attendre que l’ensemble du fichier soit analysé.
Chaque système de base de données majeur dispose désormais d’outils pour JSONL. PostgreSQL peut utiliser COPY pour les lignes via le casting jsonb, MongoDB est livré avec mongoimport et mongoexport qui utilisent JSONL par défaut, MySQL 8.0 a ajouté JSON_TABLE pour l’extraction structurée, et SQLite dispose d’une extension JSON1. Dans les sections suivantes, vous apprendrez les commandes exactes, les scripts et les bonnes pratiques pour chaque base de données.
PostgreSQL : import et export JSONL
PostgreSQL propose plusieurs approches pour travailler avec JSONL. La commande COPY fournit le chemin d’import en masse le plus rapide, tandis que le type de données jsonb vous permet de stocker et d’interroger nativement des données semi-structurées. Pour les tables structurées, vous pouvez analyser les champs JSONL en colonnes typées lors de l’import.
La façon la plus rapide d’importer du JSONL dans PostgreSQL est de charger chaque ligne comme valeur jsonb à l’aide de la commande COPY. Créez une table avec une seule colonne jsonb, puis utilisez COPY FROM pour streamer le fichier directement dans la base de données.
-- Create a staging table with a single jsonb columnCREATE TABLE staging_import (data jsonb);-- Import the JSONL file (each line becomes one row)\COPY staging_import (data) FROM 'users.jsonl';-- Verify the importSELECT count(*) FROM staging_import;SELECT data->>'name' AS name, data->>'email' AS emailFROM staging_importLIMIT 5;-- Move data into a structured tableINSERT INTO users (name, email, age)SELECTdata->>'name',data->>'email',(data->>'age')::intFROM staging_import;
Pour exporter des données en JSONL, utilisez row_to_json() ou to_jsonb() pour convertir chaque ligne en objet JSON, puis COPY le résultat vers un fichier. Chaque ligne devient une ligne dans le fichier de sortie.
-- Export entire table as JSONL\COPY (SELECT row_to_json(t)FROM (SELECT id, name, email, created_at FROM users) t) TO 'users_export.jsonl';-- Export with filtering and transformation\COPY (SELECT row_to_json(t)FROM (SELECT id, name, email,created_at::text AS created_atFROM usersWHERE active = trueORDER BY id) t) TO 'active_users.jsonl';-- Verify: each line is valid JSON-- {"id":1,"name":"Alice","email":"alice@example.com",...}
Pour les charges de travail en production, utilisez un script Python avec psycopg2 pour lire un fichier JSONL et insérer les enregistrements dans des colonnes typées. Cela vous donne un contrôle total sur la validation, la gestion des erreurs et la taille des lots.
import jsonimport psycopg2from psycopg2.extras import execute_valuesdef import_jsonl_to_postgres(file_path, conn_string):conn = psycopg2.connect(conn_string)cur = conn.cursor()batch = []batch_size = 1000total = 0with open(file_path, 'r') as f:for line_num, line in enumerate(f, 1):line = line.strip()if not line:continuetry:record = json.loads(line)batch.append((record['name'],record['email'],record.get('age'),))except (json.JSONDecodeError, KeyError) as e:print(f"Skipping line {line_num}: {e}")continueif len(batch) >= batch_size:execute_values(cur,"INSERT INTO users (name, email, age) ""VALUES %s ON CONFLICT (email) DO NOTHING",batch)total += len(batch)batch = []print(f"Imported {total} records...")if batch:execute_values(cur,"INSERT INTO users (name, email, age) ""VALUES %s ON CONFLICT (email) DO NOTHING",batch)total += len(batch)conn.commit()cur.close()conn.close()print(f"Done. Imported {total} records.")# Usageimport_jsonl_to_postgres('users.jsonl', 'postgresql://localhost/mydb')
MongoDB : support natif JSONL
MongoDB dispose d’un support JSONL de premier ordre via ses outils en ligne de commande Database Tools. Les utilitaires mongoimport et mongoexport utilisent le format JSONL par défaut, ce qui fait de MongoDB l’une des bases de données les plus faciles à utiliser pour l’échange de données JSONL. Chaque ligne d’un fichier JSONL correspond directement à un document MongoDB.
mongoimport lit un fichier JSONL et insère chaque ligne en tant que document dans la collection spécifiée. Il prend en charge le mode upsert, la conversion de types de champs et l’insertion parallèle pour un débit élevé.
# Basic import: each line becomes a documentmongoimport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--file=users.jsonl# Upsert mode: update existing documents by _idmongoimport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--file=users.jsonl \--mode=upsert \--upsertFields=email# Drop collection before import (clean slate)mongoimport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--file=users.jsonl \--drop# Import with parallel workers for large filesmongoimport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--file=large_users.jsonl \--numInsertionWorkers=4
mongoexport écrit chaque document d’une collection sous forme d’une seule ligne JSON. Vous pouvez filtrer, projeter et trier la sortie. Le résultat est un fichier JSONL valide prêt à être traité par n’importe quel système en aval.
# Export entire collection as JSONL (default format)mongoexport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--out=users_export.jsonl# Export with query filtermongoexport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--query={"active": true} \--out=active_users.jsonl# Export specific fields onlymongoexport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--fields=name,email,created_at \--out=users_partial.jsonl# Export with sortingmongoexport \--uri="mongodb://localhost:27017/mydb" \--collection=users \--sort={"created_at": -1} \--out=users_sorted.jsonl
MySQL : JSONL avec JSON_TABLE et scripts
MySQL ne dispose pas d’une commande d’import JSONL intégrée comme MongoDB, mais MySQL 8.0 a introduit JSON_TABLE qui vous permet d’extraire des données structurées à partir de chaînes JSON. Pour l’import JSONL en masse, l’approche la plus fiable combine LOAD DATA INFILE pour le chargement brut avec JSON_TABLE pour l’extraction, ou utilise un langage de script comme Python.
Chargez le fichier JSONL en tant que texte brut dans une table de staging, puis utilisez JSON_TABLE pour extraire les champs dans une table structurée. Cette approche en deux étapes fonctionne entièrement au sein de MySQL.
-- Step 1: Create a staging table for raw linesCREATE TABLE jsonl_staging (id INT AUTO_INCREMENT PRIMARY KEY,raw_line TEXT NOT NULL);-- Step 2: Load the JSONL file as raw textLOAD DATA INFILE '/var/lib/mysql-files/users.jsonl'INTO TABLE jsonl_stagingLINES TERMINATED BY '\n'(raw_line);-- Step 3: Extract structured data with JSON_TABLEINSERT INTO users (name, email, age)SELECT jt.name, jt.email, jt.ageFROM jsonl_staging,JSON_TABLE(raw_line, '$'COLUMNS (name VARCHAR(255) PATH '$.name',email VARCHAR(255) PATH '$.email',age INT PATH '$.age')) AS jt;-- Step 4: Clean up staging tableDROP TABLE jsonl_staging;-- Verify the importSELECT * FROM users LIMIT 5;
Pour plus de flexibilité, utilisez un script Python avec mysql-connector-python pour lire un fichier JSONL et insérer les enregistrements par lots. Cette approche gère efficacement les fichiers volumineux et fournit un reporting détaillé des erreurs.
import jsonimport mysql.connectordef import_jsonl_to_mysql(file_path, config):conn = mysql.connector.connect(**config)cursor = conn.cursor()batch = []batch_size = 1000total = 0insert_sql = ("INSERT INTO users (name, email, age) ""VALUES (%s, %s, %s) ""ON DUPLICATE KEY UPDATE name=VALUES(name)")with open(file_path, 'r') as f:for line_num, line in enumerate(f, 1):line = line.strip()if not line:continuetry:record = json.loads(line)batch.append((record['name'],record['email'],record.get('age'),))except (json.JSONDecodeError, KeyError) as e:print(f"Skipping line {line_num}: {e}")continueif len(batch) >= batch_size:cursor.executemany(insert_sql, batch)conn.commit()total += len(batch)batch = []print(f"Imported {total} records...")if batch:cursor.executemany(insert_sql, batch)conn.commit()total += len(batch)cursor.close()conn.close()print(f"Done. Imported {total} records.")# Usageimport_jsonl_to_mysql('users.jsonl', {'host': 'localhost','user': 'root','password': 'secret','database': 'mydb'})
SQLite : import JSONL léger
SQLite est un excellent choix pour le développement local et les petits jeux de données. Bien que SQLite ne dispose pas d’une commande d’import JSONL native, son extension JSON1 fournit json_extract() pour travailler avec les données JSON, et un simple script Python peut importer des fichiers JSONL efficacement grâce au support intégré des transactions de SQLite.
Utilisez le module sqlite3 intégré de Python pour lire un fichier JSONL et insérer les enregistrements dans une base de données SQLite. Regrouper toutes les insertions dans une seule transaction améliore considérablement les performances pour les fichiers volumineux.
import jsonimport sqlite3def import_jsonl_to_sqlite(jsonl_path, db_path):conn = sqlite3.connect(db_path)cursor = conn.cursor()# Create table if it doesn't existcursor.execute("""CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,email TEXT UNIQUE,age INTEGER,raw_json TEXT)""")total = 0errors = 0with open(jsonl_path, 'r') as f:# Use a transaction for bulk insert performanceconn.execute('BEGIN TRANSACTION')for line_num, line in enumerate(f, 1):line = line.strip()if not line:continuetry:record = json.loads(line)cursor.execute("INSERT OR IGNORE INTO users ""(name, email, age, raw_json) ""VALUES (?, ?, ?, ?)",(record['name'],record.get('email'),record.get('age'),line, # Store original JSON))total += 1except (json.JSONDecodeError, KeyError) as e:errors += 1print(f"Line {line_num}: {e}")conn.commit()conn.close()print(f"Imported {total} records, {errors} errors")# Usageimport_jsonl_to_sqlite('users.jsonl', 'app.db')# Query with json_extract (SQLite JSON1 extension)# SELECT json_extract(raw_json, '$.name') FROM users;
Bonnes pratiques d’import en masse
L’import de fichiers JSONL volumineux dans une base de données nécessite une attention particulière aux transactions, à la gestion des erreurs et à la gestion des ressources. Ces bonnes pratiques s’appliquent à tous les systèmes de base de données et vous aideront à construire des pipelines d’import fiables et prêts pour la production.
Transactions par lots
PerformanceN’insérez jamais une seule ligne par transaction. Regroupez les insertions par lots de 500 à 5 000 lignes par transaction. Cela réduit les E/S disque et la surcharge de verrouillage de 10 à 100 fois. La plupart des bases de données obtiennent les meilleurs gains avec des tailles de lot de 1 000. Aller au-delà offre des rendements décroissants et augmente le coût d’un rollback en cas de problème.
Gestion des erreurs ligne par ligne
FiabilitéAnalysez et validez chaque ligne JSONL individuellement. Enregistrez le numéro de ligne et le message d’erreur pour chaque ligne qui échoue à la validation ou à l’insertion. Utilisez ON CONFLICT / ON DUPLICATE KEY pour gérer les violations de contrainte d’unicité avec élégance plutôt que d’interrompre l’import entier. Enregistrez les lignes en échec dans un fichier d’erreurs séparé pour un examen ultérieur.
Suivi de la progression
ObservabilitéPour les fichiers de millions de lignes, enregistrez la progression tous les N enregistrements (par exemple, tous les 10 000). Suivez le nombre total de lignes lues, les insertions réussies, les doublons ignorés et les erreurs. Calculez et affichez le taux d’import (enregistrements/seconde) pour identifier les goulots d’étranglement de performance. Ce retour d’information est essentiel pour surveiller les imports de longue durée.
Ce pattern générique combine le traitement par lots, la gestion des erreurs et le suivi de la progression. Adaptez-le à n’importe quelle base de données en remplaçant la fonction d’insertion.
import jsonimport timedef batch_import_jsonl(file_path, insert_fn, batch_size=1000):"""Generic JSONL batch importer with error handling."""batch = []stats = {'total_lines': 0,'imported': 0,'skipped': 0,'errors': 0}start_time = time.time()error_file = open(file_path + '.errors', 'w')with open(file_path, 'r') as f:for line_num, line in enumerate(f, 1):stats['total_lines'] = line_numline = line.strip()if not line:stats['skipped'] += 1continuetry:record = json.loads(line)batch.append(record)except json.JSONDecodeError as e:stats['errors'] += 1error_file.write(f"{line_num}\t{e}\t{line}\n")continueif len(batch) >= batch_size:inserted = insert_fn(batch)stats['imported'] += insertedbatch = []if line_num % 10000 == 0:elapsed = time.time() - start_timerate = stats['imported'] / elapsedprint(f"Progress: {line_num:,} lines | "f"{stats['imported']:,} imported | "f"{rate:,.0f} records/sec")# Flush remaining batchif batch:inserted = insert_fn(batch)stats['imported'] += insertederror_file.close()elapsed = time.time() - start_timeprint(f"\nComplete in {elapsed:.1f}s")print(f" Lines: {stats['total_lines']:,}")print(f" Imported: {stats['imported']:,}")print(f" Errors: {stats['errors']:,}")return stats
Préparez vos données avec des outils JSONL gratuits
Avant d’importer du JSONL dans votre base de données, validez le format du fichier et convertissez entre formats. Nos outils en ligne gratuits traitent tout localement dans votre navigateur, vos données ne quittent donc jamais votre machine.