JSONL Database Import & Export: PostgreSQL, MongoDB & Meer
Een uitgebreide gids voor het importeren van JSONL-bestanden in databases en het exporteren van databaserecords als JSONL. Behandelt PostgreSQL COPY-commando's, MongoDB CLI-tools, MySQL JSON_TABLE, SQLite-scripts en productie-klare bulkimportpatronen.
Laatst bijgewerkt: februari 2026
Waarom JSONL Gebruiken voor Database Import & Export?
JSONL (JSON Lines) is een voorkeursformaat geworden voor het verplaatsen van gegevens tussen databases en externe systemen. Elke regel is een onafhankelijk, op zichzelf staand JSON-object, wat betekent dat je records één voor één kunt streamen zonder de volledige dataset in het geheugen te laden. Dit is cruciaal wanneer je miljoenen rijen migreert tussen PostgreSQL-instanties, MongoDB-collecties synchroniseert naar een datawarehouse, of database-exports voedt aan machine learning-pipelines.
Vergeleken met CSV behoudt JSONL gegevenstypen, ondersteunt het geneste objecten en arrays, en elimineert het de ambiguiteit van scheidingsteken-escaping. Een JSONL-bestand kan een PostgreSQL jsonb-kolom exact zoals het is overbrengen, terwijl CSV zou vereisen dat je de geneste structuur plat maakt of escaped. Vergeleken met een volledige JSON-array is JSONL streambaar: je kunt elk record verwerken, valideren of transformeren op het moment dat het wordt gelezen, in plaats van te wachten tot het hele bestand is geparseerd.
Elk groot databasesysteem heeft nu tooling voor JSONL. PostgreSQL kan rijen COPY'en via jsonb-casting, MongoDB wordt geleverd met mongoimport en mongoexport die standaard JSONL gebruiken, MySQL 8.0 heeft JSON_TABLE toegevoegd voor gestructureerde extractie, en SQLite heeft een JSON1-extensie. In de volgende secties leer je de exacte commando's, scripts en best practices voor elke database.
PostgreSQL: JSONL Importeren & Exporteren
PostgreSQL biedt verschillende benaderingen voor het werken met JSONL. Het COPY-commando biedt het snelste pad voor bulkimport, terwijl het jsonb-gegevenstype je in staat stelt semi-gestructureerde gegevens native op te slaan en te bevragen. Voor gestructureerde tabellen kun je JSONL-velden parseren naar getypeerde kolommen tijdens import.
De snelste manier om JSONL in PostgreSQL te importeren is om elke regel als een jsonb-waarde te laden met het COPY-commando. Maak een tabel met een enkele jsonb-kolom en gebruik vervolgens COPY FROM om het bestand rechtstreeks in de database te streamen.
-- 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;
Om gegevens als JSONL te exporteren, gebruik je row_to_json() of to_jsonb() om elke rij naar een JSON-object te converteren, en vervolgens COPY je het resultaat naar een bestand. Elke rij wordt één regel in het uitvoerbestand.
-- 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",...}
Voor productie-workloads gebruik je een Python-script met psycopg2 om een JSONL-bestand te lezen en records in te voegen in getypeerde kolommen. Dit geeft je volledige controle over validatie, foutafhandeling en batchgrootte.
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: Native JSONL-ondersteuning
MongoDB heeft eersteklas JSONL-ondersteuning via zijn opdrachtregeltools (Database Tools). De mongoimport- en mongoexport-hulpprogramma's gebruiken standaard het JSONL-formaat, waardoor MongoDB een van de eenvoudigste databases is om mee te werken voor JSONL-gegevensuitwisseling. Elke regel in een JSONL-bestand wordt rechtstreeks gekoppeld aan een MongoDB-document.
mongoimport leest een JSONL-bestand en voegt elke regel in als een document in de opgegeven collectie. Het ondersteunt upsert-modus, veldtype-conversie en parallelle invoeging voor hoge doorvoer.
# 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 schrijft elk document in een collectie als een enkele JSON-regel. Je kunt de uitvoer filteren, projecteren en sorteren. Het resultaat is een geldig JSONL-bestand dat klaar is voor verwerking door elk downstream-systeem.
# 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 met JSON_TABLE & Scripts
MySQL heeft geen ingebouwd JSONL-importcommando zoals MongoDB, maar MySQL 8.0 introduceerde JSON_TABLE waarmee je gestructureerde gegevens uit JSON-strings kunt extraheren. Voor bulkimport van JSONL is de meest betrouwbare aanpak een combinatie van LOAD DATA INFILE voor het laden van ruwe gegevens met JSON_TABLE voor extractie, of het gebruik van een scripttaal zoals Python.
Laad het JSONL-bestand als ruwe tekst in een stagingtabel en gebruik vervolgens JSON_TABLE om velden naar een gestructureerde tabel te extraheren. Deze tweestapsaanpak werkt volledig binnen 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;
Voor meer flexibiliteit gebruik je een Python-script met mysql-connector-python om een JSONL-bestand te lezen en records batchgewijs in te voegen. Deze aanpak verwerkt grote bestanden efficiënt en biedt gedetailleerde foutrapportage.
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: Lichtgewicht JSONL-import
SQLite is een uitstekende keuze voor lokale ontwikkeling en kleinere datasets. Hoewel SQLite geen native JSONL-importcommando heeft, biedt de JSON1-extensie json_extract() voor het werken met JSON-gegevens, en een eenvoudig Python-script kan JSONL-bestanden efficiënt importeren met de ingebouwde transactie-ondersteuning van SQLite.
Gebruik Python's ingebouwde sqlite3-module om een JSONL-bestand te lezen en records in te voegen in een SQLite-database. Het inpakken van alle invoegingen in een enkele transactie verbetert de prestaties dramatisch voor grote bestanden.
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 Practices voor Bulkimport
Het importeren van grote JSONL-bestanden in een database vereist zorgvuldige aandacht voor transacties, foutafhandeling en resourcebeheer. Deze best practices zijn van toepassing op alle databasesystemen en helpen je betrouwbare, productie-klare importpipelines te bouwen.
Batchtransacties
PrestatieVoeg nooit één rij per transactie in. Groepeer invoegingen in batches van 500-5000 rijen per transactie. Dit vermindert schijf-I/O en lock-overhead met 10-100x. De meeste databases zien de grootste winst bij batchgroottes van 1000. Groter gaan biedt afnemende meeropbrengsten en verhoogt de kosten van een rollback als er iets misgaat.
Foutafhandeling per Regel
BetrouwbaarheidParseer en valideer elke JSONL-regel individueel. Log het regelnummer en de foutmelding voor elke regel die validatie of invoeging niet doorstaat. Gebruik ON CONFLICT / ON DUPLICATE KEY om schendingen van unieke beperkingen elegant af te handelen in plaats van de hele import af te breken. Sla mislukte regels op in een apart foutenbestand voor latere beoordeling.
Voortgangsregistratie
ObserveerbaarheidLog bij bestanden met miljoenen regels de voortgang elke N records (bijvoorbeeld elke 10.000). Houd het totaal aantal gelezen regels, succesvolle invoegingen, overgeslagen duplicaten en fouten bij. Bereken en toon de importsnelheid (records/seconde) om prestatieknelpunten te identificeren. Deze feedback is essentieel voor het monitoren van langlopende imports.
Dit generieke patroon combineert batching, foutafhandeling en voortgangsregistratie. Pas het aan voor elke database door de invoegfunctie te vervangen.
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
Bereid Je Gegevens Voor met Gratis JSONL-tools
Valideer het bestandsformaat en converteer tussen formaten voordat je JSONL in je database importeert. Onze gratis online tools verwerken alles lokaal in je browser, zodat je gegevens nooit je machine verlaten.