Import ed Export JSONL da Database: PostgreSQL, MongoDB e Altri
Una guida completa all'importazione di file JSONL nei database e all'esportazione di record del database come JSONL. Copre i comandi COPY di PostgreSQL, gli strumenti CLI di MongoDB, JSON_TABLE di MySQL, script SQLite e pattern di import in blocco pronti per la produzione.
Ultimo aggiornamento: Febbraio 2026
Perché Usare JSONL per Import ed Export da Database?
JSONL (JSON Lines) è diventato un formato preferito per spostare dati tra database e sistemi esterni. Ogni riga è un oggetto JSON indipendente e autonomo, il che significa che puoi trasmettere record uno alla volta senza caricare l'intero dataset in memoria. Questo è fondamentale quando migri milioni di righe tra istanze PostgreSQL, sincronizzi collezioni MongoDB con un data warehouse o alimenti esportazioni di database in pipeline di machine learning.
Rispetto a CSV, JSONL preserva i tipi di dati, supporta oggetti e array nidificati ed elimina l'ambiguità dell'escape dei delimitatori. Un file JSONL può trasportare una colonna jsonb di PostgreSQL esattamente così com'è, mentre CSV richiederebbe di appiattire o fare l'escape della struttura nidificata. Rispetto a un array JSON completo, JSONL è in streaming: puoi elaborare, validare o trasformare ogni record nel momento in cui viene letto, piuttosto che aspettare che l'intero file venga analizzato.
Ogni sistema di database principale ora dispone di strumenti per JSONL. PostgreSQL può fare COPY delle righe tramite casting jsonb, MongoDB include mongoimport e mongoexport che usano JSONL come default, MySQL 8.0 ha aggiunto JSON_TABLE per l'estrazione strutturata, e SQLite ha un'estensione JSON1. Nelle sezioni seguenti imparerai i comandi esatti, gli script e le best practice per ogni database.
PostgreSQL: Import ed Export JSONL
PostgreSQL offre diversi approcci per lavorare con JSONL. Il comando COPY fornisce il percorso di import in blocco più veloce, mentre il tipo di dato jsonb permette di memorizzare e interrogare dati semi-strutturati nativamente. Per tabelle strutturate, puoi analizzare i campi JSONL in colonne tipizzate durante l'import.
Il modo più veloce per importare JSONL in PostgreSQL è caricare ogni riga come valore jsonb usando il comando COPY. Crea una tabella con una singola colonna jsonb, poi usa COPY FROM per trasmettere il file direttamente nel database.
-- 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;
Per esportare dati come JSONL, usa row_to_json() o to_jsonb() per convertire ogni riga in un oggetto JSON, poi usa COPY per salvare il risultato in un file. Ogni riga diventa una riga nel file di output.
-- 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",...}
Per carichi di lavoro di produzione, usa uno script Python con psycopg2 per leggere un file JSONL e inserire record in colonne tipizzate. Questo ti dà pieno controllo su validazione, gestione degli errori e dimensione dei batch.
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: Supporto Nativo JSONL
MongoDB ha supporto JSONL di prima classe tramite i suoi strumenti Database Tools da riga di comando. Le utility mongoimport e mongoexport usano il formato JSONL come default, rendendo MongoDB uno dei database più facili con cui lavorare per lo scambio di dati JSONL. Ogni riga in un file JSONL corrisponde direttamente a un documento MongoDB.
mongoimport legge un file JSONL e inserisce ogni riga come documento nella collezione specificata. Supporta la modalità upsert, la coercizione dei tipi di campo e l'inserimento parallelo per un throughput elevato.
# 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 scrive ogni documento di una collezione come una singola riga JSON. Puoi filtrare, proiettare e ordinare l'output. Il risultato è un file JSONL valido pronto per l'elaborazione da qualsiasi sistema a valle.
# 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 con JSON_TABLE e Script
MySQL non ha un comando nativo di import JSONL come MongoDB, ma MySQL 8.0 ha introdotto JSON_TABLE che permette di estrarre dati strutturati da stringhe JSON. Per l'import in blocco di JSONL, l'approccio più affidabile combina LOAD DATA INFILE per il caricamento grezzo con JSON_TABLE per l'estrazione, oppure usa un linguaggio di scripting come Python.
Carica il file JSONL come testo grezzo in una tabella di staging, poi usa JSON_TABLE per estrarre i campi in una tabella strutturata. Questo approccio in due fasi funziona interamente all'interno di 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;
Per maggiore flessibilità, usa uno script Python con mysql-connector-python per leggere un file JSONL e inserire record in batch. Questo approccio gestisce file di grandi dimensioni in modo efficiente e fornisce report dettagliati degli errori.
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 Leggero
SQLite è un'eccellente scelta per lo sviluppo locale e dataset di dimensioni ridotte. Sebbene SQLite non abbia un comando nativo di import JSONL, la sua estensione JSON1 fornisce json_extract() per lavorare con dati JSON, e un semplice script Python può importare file JSONL in modo efficiente usando il supporto integrato alle transazioni di SQLite.
Usa il modulo sqlite3 integrato di Python per leggere un file JSONL e inserire record in un database SQLite. Racchiudere tutti gli inserimenti in una singola transazione migliora drasticamente le prestazioni per file di grandi dimensioni.
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;
Best Practice per l'Import in Blocco
L'importazione di file JSONL di grandi dimensioni in un database richiede attenzione a transazioni, gestione degli errori e gestione delle risorse. Queste best practice si applicano a tutti i sistemi di database e ti aiuteranno a costruire pipeline di import affidabili e pronte per la produzione.
Transazioni in Batch
PrestazioniNon inserire mai una riga per transazione. Raggruppa gli inserimenti in batch di 500-5000 righe per transazione. Questo riduce l'I/O su disco e l'overhead dei lock di 10-100x. La maggior parte dei database vede i maggiori guadagni con batch di 1000 righe. Andare oltre offre rendimenti decrescenti e aumenta il costo di un rollback in caso di errore.
Gestione Errori a Livello di Riga
AffidabilitàAnalizza e valida ogni riga JSONL individualmente. Registra il numero di riga e il messaggio di errore per ogni riga che fallisce la validazione o l'inserimento. Usa ON CONFLICT / ON DUPLICATE KEY per gestire le violazioni di vincoli univoci in modo elegante anziché interrompere l'intero import. Salva le righe fallite in un file di errori separato per la revisione successiva.
Monitoraggio dell'Avanzamento
OsservabilitàPer file con milioni di righe, registra l'avanzamento ogni N record (ad esempio, ogni 10.000). Tieni traccia delle righe totali lette, degli inserimenti riusciti, dei duplicati saltati e degli errori. Calcola e mostra la velocità di import (record/secondo) per identificare i colli di bottiglia delle prestazioni. Questo feedback è essenziale per monitorare import di lunga durata.
Questo pattern generico combina batch, gestione degli errori e monitoraggio dell'avanzamento. Adattalo a qualsiasi database sostituendo la funzione di inserimento.
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
Prepara i Tuoi Dati con Strumenti JSONL Gratuiti
Prima di importare JSONL nel tuo database, valida il formato del file e converti tra formati. I nostri strumenti online gratuiti elaborano tutto localmente nel tuo browser, quindi i tuoi dati non lasciano mai la tua macchina.