CSV naar JSON omzetten: methoden, valkuilen & aanbevolen aanpak
Je operationeel team stuurt je een CSV-export. Je API verwacht JSON. Je opent het bestand, staart naar 10.000 rijen kommagescheiden waarden, en vraagt je af: wat is de snelste manier om CSV naar JSON om te zetten zonder gegevens te verliezen?
Deze handleiding behandelt vier conversiemethoden (browser-tool, JavaScript, Python, CLI), de omgekeerde richting (JSON naar CSV), vijf valkuilen die je data stilletjes beschadigen, en hoe je bestanden verwerkt die te groot zijn voor het geheugen.
CSV vs JSON: wanneer gebruik je wat?
Voordat je omzet, helpt het te begrijpen waar elk formaat goed in is.
| Dimensie | CSV | JSON |
|---|---|---|
| Structuur | Platte tabel (rijen en kolommen) | Geneste hiërarchie (objecten, arrays) |
| Gegevenstypen | Alles is een string | string, number, boolean, null |
| Leesbaarheid | Spreadsheet-vriendelijk | Ontwikkelaar-vriendelijk |
| Primair gebruik | Data-export/import, rapporten, ETL | API’s, configuratiebestanden, NoSQL-opslag |
| Bestandsgrootte | Kleiner (geen herhaalde sleutelnamen) | Groter (sleutelnamen herhalen per record) |
| Schema | Impliciet (kopregel) | Expliciet (of gebruik JSON Schema) |
Vuistregel: Gebruik CSV als je data tabellair is en de afnemer een spreadsheet of datapipeline is. Gebruik JSON als je data hiërarchie heeft of de afnemer een API is. Je kunt je JSON-uitvoer altijd valideren met een JSON Formatter om structurele problemen vroeg op te sporen.
Als je project gebruikmaakt van soepelere JSON-formaten zoals JSON5 of JSONC voor configuratie, zie onze handleiding voor JSON5 en JSONC formatteren voor syntaxverschillen en tooling.
4 manieren om CSV naar JSON om te zetten
Methode 1 — Tool die in de browser draait
Voor eenmalige conversies is een tool die in de browser draait de snelste aanpak. Plak je CSV in een online converter, krijg JSON terug en valideer het resultaat vervolgens in een JSON Formatter om te bevestigen dat de structuur klopt.
Het voordeel: je data verlaat nooit je browser. Geen uploads, geen serververwerking, geen privacyproblemen. Dit is bepalend voor situaties waarin je werkt met interne data, API-sleutels in exports, of alles wat je liever niet naar een externe server stuurt.
Geschikt voor: kleine bestanden (onder 10 MB), snelle eenmalige conversies en niet-technische teamleden.
Methode 2 — JavaScript / Node.js
Browser (vanilla JS):
function csvToJson(csv) {
const lines = csv.trim().split('\n');
const headers = lines[0].split(',').map(h => h.trim());
return lines.slice(1).map(line => {
const values = line.split(',');
return headers.reduce((obj, header, i) => {
obj[header] = values[i]?.trim() ?? '';
return obj;
}, {});
});
}
const csv = `name,age,city
Alice,30,New York
Bob,25,London`;
console.log(JSON.stringify(csvToJson(csv), null, 2));
Dit werkt voor eenvoudige CSV zonder velden met aanhalingstekens. Voor productiegebruik met komma’s in waarden, regeleinden in velden of strings met aanhalingstekens gebruik je een volwaardige verwerker.
Node.js (csv-parser + streams):
import { createReadStream } from 'fs';
import { parse } from 'csv-parse';
const records = [];
createReadStream('data.csv')
.pipe(parse({ columns: true, trim: true, skip_empty_lines: true }))
.on('data', (row) => records.push(row))
.on('end', () => {
console.log(JSON.stringify(records, null, 2));
});
De optie columns: true gebruikt de eerste rij als sleutels. De optie trim verwijdert witruimte uit waarden. Dit verwerkt velden met aanhalingstekens, ge-escapete komma’s en meerdere regels correct.
Methode 3 — Python
Standaardbibliotheek (geen extra afhankelijkheden):
import csv
import json
with open('data.csv', encoding='utf-8') as f:
reader = csv.DictReader(f)
rows = list(reader)
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(rows, f, indent=2, ensure_ascii=False)
csv.DictReader koppelt elke rij aan een dictionary met de kopregel als sleutels. De vlag ensure_ascii=False behoudt Unicode-tekens (Chinees, Japans, tekens met accenten) in plaats van ze te escapen naar \uXXXX.
Pandas (one-liner voor data scientists):
import pandas as pd
df = pd.read_csv('data.csv')
df.to_json('data.json', orient='records', indent=2, force_ascii=False)
Wanneer gebruik je wat:
- csv + json: Lichte scripts, Lambda-functies, containers waarvoor je minimale afhankelijkheden wilt.
- pandas: Als je de data ook wilt opschonen, filteren of transformeren voor de conversie. De overhead van het importeren van pandas is de moeite waard als je meer doet dan alleen formaatconversie.
Methode 4 — CLI-tools
Voor shell-scripts en automatiseringspipelines:
csvkit:
# Install: pip install csvkit
csvjson data.csv > data.json
Miller (mlr):
# Install: brew install miller (macOS) or apt install miller (Ubuntu)
mlr --csv --json cat data.csv > data.json
Pipe met jq voor filteren:
# Convert and filter in one pipeline
csvjson data.csv | jq '[.[] | select(.age | tonumber > 25)]'
Miller is bijzonder krachtig omdat het CSV, JSON, TSV en andere formaten ingebouwd ondersteunt. Je kunt data transformeren tijdens de conversie:
# Convert CSV to JSON, rename a field, add a computed field
mlr --csv --json rename name,fullName then put '$age_group = ($age > 30) ? "senior" : "junior"' data.csv
JSON naar CSV: de omgekeerde richting
JSON naar CSV omzetten kent uitdagingen die in de andere richting niet bestaan.
Geneste objecten platslaan
CSV is inherent plat. Als je JSON geneste objecten heeft, heb je een strategie nodig om ze plat te slaan:
{
"name": "Alice",
"address": {
"city": "New York",
"zip": "10001"
}
}
Wordt:
| name | address.city | address.zip |
|---|---|---|
| Alice | New York | 10001 |
De puntnotatieconventie (address.city) is de meest gebruikte aanpak. In Python:
import pandas as pd
data = [
{"name": "Alice", "address": {"city": "New York", "zip": "10001"}},
{"name": "Bob", "address": {"city": "London", "zip": "EC1A"}}
]
df = pd.json_normalize(data)
df.to_csv('output.csv', index=False)
# Columns: name, address.city, address.zip
Arrays verwerken
Arrayvelden vereisen een keuze:
| Strategie | Voorbeeldinvoer | CSV-uitvoer | Geschikt voor |
|---|---|---|---|
| Samenvoegen als string | ["admin","editor"] | admin;editor | Eenvoudige lijsten, her-importeerbaar |
| Uitbreiden naar kolommen | ["admin","editor"] | role_0: admin, role_1: editor | Arrays met vaste lengte |
| Uitbreiden naar rijen | ["admin","editor"] | Twee rijen, één per rol | Relationele analyse |
Kies op basis van je afnemer. Als de CSV naar een database gaat, is uitbreiden naar rijen meestal de beste keuze.
Verlies van type-informatie
CSV heeft geen typesysteem. Als je JSON naar CSV omzet:
truewordt de string"true"— is het een boolean of een string?nullwordt een lege cel — niet te onderscheiden van een lege string""42wordt"42"— is het een getal of een string?
Als round-trip nauwkeurigheid belangrijk is (CSV → verwerking → JSON), documenteer je typeconventies in een kopcommentaar of een bijbehorend schemabestand.
5 veelvoorkomende valkuilen en hoe je ze vermijdt
Deze problemen beschadigen data zonder dat je het merkt. De meeste tutorials slaan ze over. Kom er niet pas in productie achter.
1. Coderingsvalkuilen
Het probleem: Je opent een CSV van een collega en ziet é in plaats van é, of 锟斤拷 in plaats van Chinese tekens.
Waarom dit gebeurt: Het bestand is opgeslagen in één codering (Windows-1252, GBK, Shift_JIS) maar je verwerker gaat uit van UTF-8. Excel op Windows slaat CSV vaak op als Windows-1252 of voegt een UTF-8 BOM toe (Byte Order Mark — de onzichtbare \xEF\xBB\xBF aan het begin van het bestand).
De oplossing:
# Detect encoding first
import chardet
with open('data.csv', 'rb') as f:
result = chardet.detect(f.read(10000))
print(result) # {'encoding': 'Windows-1252', 'confidence': 0.73}
# Then read with the correct encoding
with open('data.csv', encoding=result['encoding']) as f:
reader = csv.DictReader(f)
# ...
In Node.js verwijder je de BOM expliciet:
import { readFileSync } from 'fs';
let content = readFileSync('data.csv', 'utf-8');
// Strip UTF-8 BOM if present
if (content.charCodeAt(0) === 0xFEFF) {
content = content.slice(1);
}
2. Verwarring over het scheidingsteken
Het probleem: Je verwerker produceert één grote kolom in plaats van meerdere velden.
Waarom dit gebeurt: In veel Europese regio’s (Frankrijk, Duitsland, Spanje) gebruikt Excel puntkomma’s (;) als CSV-scheidingsteken, omdat komma’s worden gebruikt als decimaalteken (bijv. 3,14 in plaats van 3.14). Tab-gescheiden bestanden (.tsv) voegen nog een variant toe.
De oplossing: Detecteer het scheidingsteken automatisch door de eerste paar regels in te lezen:
import csv
with open('data.csv') as f:
sample = f.read(8192)
dialect = csv.Sniffer().sniff(sample, delimiters=',;\t|')
f.seek(0)
reader = csv.DictReader(f, dialect=dialect)
3. Voorloopnullen verdwijnen
Het probleem: Postcode 00501 wordt 501. Productcode 007 wordt 7.
Waarom dit gebeurt: De verwerker (of Excel) interpreteert het veld als een getal en verwijdert de voorloopnullen. Dit is bijzonder gevaarlijk bij postcodes, telefoonnummers en ID-codes.
De oplossing: Forceer string-typering. In pandas:
df = pd.read_csv('data.csv', dtype={'zip': str, 'product_code': str})
In JavaScript controleer je of de originele string verschilt van de numerieke verwerking:
function preserveLeadingZeros(value) {
if (/^0\d+$/.test(value)) return value; // Keep as string
const num = Number(value);
return isNaN(num) ? value : num;
}
4. Precisieverlies bij grote getallen
Het probleem: ID 9007199254740993 wordt 9007199254740992 in je JSON.
Waarom dit gebeurt: JavaScript Number is een 64-bit float (IEEE 754). Gehele getallen boven Number.MAX_SAFE_INTEGER (2^53 - 1 = 9007199254740991) verliezen precisie. Dit treft database-ID’s, Snowflake ID’s en Twitter/X-post-ID’s.
De oplossing: Bewaar grote getallen als strings in JSON, of gebruik BigInt in je verwerkingscode:
// Parse with string preservation for large numbers
function safeParseNumber(value) {
const num = Number(value);
if (Number.isInteger(num) && !Number.isSafeInteger(num)) {
return value; // Keep as string to preserve precision
}
return isNaN(num) ? value : num;
}
5. Onduidelijkheid bij lege waarden
Het probleem: Je CSV heeft lege cellen. Na de conversie kun je niet meer zien of de oorspronkelijke waarde een lege string "" was, null, of gewoon ontbrak.
Waarom dit gebeurt: CSV heeft geen manier om onderscheid te maken tussen deze drie toestanden. Een leeg veld tussen twee komma’s (Alice,,30) kan elk van de drie betekenen.
De oplossing: Definieer een conventie en pas die consistent toe:
def parse_value(value):
if value == '':
return None # or '' — pick one convention
if value == 'NULL' or value == 'null':
return None
return value
Als je data schildwachtwaarden gebruikt zoals NULL, N/A of -, documenteer ze en verwerk ze expliciet.
Grote bestanden streamen
Als je CSV meer dan 100 MB beslaat, is het volledig in het geheugen laden geen optie. Gebruik streaming.
Node.js (stream pipeline):
import { createReadStream, createWriteStream } from 'fs';
import { parse } from 'csv-parse';
import { Transform } from 'stream';
import { pipeline } from 'stream/promises';
let first = true;
const toJsonArray = new Transform({
objectMode: true,
transform(record, encoding, callback) {
const prefix = first ? '[\n' : ',\n';
first = false;
callback(null, prefix + JSON.stringify(record));
},
flush(callback) {
callback(null, '\n]');
}
});
await pipeline(
createReadStream('large.csv'),
parse({ columns: true, trim: true }),
toJsonArray,
createWriteStream('large.json')
);
Python (generator):
import csv
import json
def csv_rows(path):
with open(path, encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
yield row
# Stream to JSON Lines format (one JSON object per line)
with open('large.jsonl', 'w', encoding='utf-8') as out:
for row in csv_rows('large.csv'):
out.write(json.dumps(row, ensure_ascii=False) + '\n')
Voor zeer grote bestanden overweeg je JSON Lines (.jsonl) in plaats van één grote JSON-array. Elke regel is een zelfstandig JSON-object, wat betekent dat je het uitvoerbestand ook regel voor regel kunt verwerken — je hoeft niet het hele bestand in te laden.
Veelgestelde vragen
Wat is het verschil tussen CSV en JSON?
CSV (Comma-Separated Values) slaat data op als een platte tabel waarbij elke waarde een string is. JSON (JavaScript Object Notation) slaat gestructureerde data op met geneste objecten, arrays en getypeerde waarden (strings, getallen, booleans, null). CSV is kleiner en spreadsheet-vriendelijk; JSON is expressiever en API-vriendelijk.
Hoe zet ik CSV om naar JSON in JavaScript?
Gebruik het pakket csv-parse in Node.js: lees het bestand met createReadStream, stuur het door parse({ columns: true }) en verzamel de records. Voor browsergebruik lees je het bestand met FileReader, splits je op regeleinden en zet je rijen om naar objecten met de kopregel als sleutels.
Hoe zet ik CSV om naar JSON in Python?
Gebruik csv.DictReader uit de standaardbibliotheek om rijen als dictionaries in te lezen, dan json.dump() om ze als JSON-array te schrijven. Voor datamanipulatie voor de conversie is pandas.read_csv() gevolgd door df.to_json(orient='records') een one-liner alternatief.
Kan geneste JSON worden omgezet naar CSV?
Ja, maar je hebt een strategie nodig om te platslaan. De meest gebruikte aanpak gebruikt puntnotatie: een veld als address.city wordt een kolomkoptekst. In Python verwerkt pandas.json_normalize() dit automatisch. Arrays vereisen extra keuzes — samenvoegen als strings, uitbreiden naar kolommen of uitbreiden naar rijen.
Waarom bevat mijn CSV onleesbare tekens na de conversie?
Coderings-mismatch. Het bestand is waarschijnlijk opgeslagen in Windows-1252 of GBK, maar je verwerker gaat uit van UTF-8. Gebruik een detectiebibliotheek zoals chardet (Python) om de codering te achterhalen en geef die vervolgens expliciet op bij het lezen. Controleer ook op een UTF-8 BOM die sommige tools automatisch toevoegen.
Hoe verwerk ik een CSV-bestand van meer dan 100 MB?
Gebruik streaming in plaats van het hele bestand in het geheugen te laden. In Node.js stuur je het door csv-parse met streams. In Python itereer je met csv.DictReader via een generator. Overweeg JSON Lines (.jsonl) als uitvoerformaat in plaats van één JSON-array — dat maakt verdere verwerking eenvoudiger.
Hoe kan ik controleren of mijn geconverteerde JSON geldig is?
Plak de uitvoer in een online JSON Formatter om syntaxis, structuur en nesting te controleren. Voor geautomatiseerde validatie gebruik je JSON.parse() in JavaScript of json.loads() in Python — beide geven duidelijke fouten bij ongeldige invoer. Voor schemavalidatie definieer je een JSON Schema en valideer je programmatisch.
Belangrijkste punten
- Kies de juiste methode voor je situatie: browser-tools voor snelle eenmalige conversies, code voor automatisering, CLI voor pipelines.
- Let op coderingsproblemen — geef de codering altijd expliciet op in plaats van te vertrouwen op standaardinstellingen.
- Behoud typen bewust — voorloopnullen, grote gehele getallen en null-waarden vereisen allemaal expliciete verwerking.
- Stream grote bestanden in plaats van ze in het geheugen te laden. Overweeg JSON Lines-formaat voor zeer grote datasets.
- Valideer je uitvoer — stuur geconverteerde JSON door een JSON Formatter om structurele problemen op te sporen voordat ze in productie gaan.