CSV to JSON JavaScript — Converter + Code Examples

·Front-end & Node.js Developer·Beoordeeld doorSophie Laurent·Gepubliceerd

Gebruik de gratis CSV to JSON direct in je browser — geen installatie nodig.

CSV to JSON online uitproberen →

De meeste CSV-data die ik tegenkom arriveert als een platte string vanuit een bestandsupload, een database-export of een API die nog steeds het formaat uit de jaren 70 spreekt. Om CSV naar JSON te converteren in JavaScript, heb je twee dingen nodig die de taal je gratis geeft: string-splitting om de rijen te parsen en JSON.stringify() om het resultaat te serialiseren. Geen npm-pakketten nodig voor de basis — deze gids behandelt de volledige pipeline van een herbruikbare csvToJson() utility tot PapaParse en Node.js bestand-I/O. Voor snelle conversies zonder code verwerkt de online CSV naar JSON converter het direct. Alle voorbeelden zijn gericht op Node.js 18+ en moderne browsers.

  • Splits CSV op regeleinde, haal headers op uit rij 0, map de overige rijen naar objecten, en gebruik JSON.stringify(array, null, 2) voor opgemaakte uitvoer.
  • JSON.stringify() produceert een string; JSON.parse() zet het terug naar een actieve JavaScript-array — weet welke je hebt voordat je ermee werkt.
  • Map-instanties serialiseren niet automatisch naar JSON — roep eerst Object.fromEntries(map) aan.
  • Gebruik PapaParse of csv-parse voor CSV met aangehaalde velden, komma's in waarden of regeleinden in cellen in plaats van handmatig te splitsen.
  • csvtojson (npm) verwerkt typeconversie, streaming en RFC 4180-randgevallen in één aanroep.

Wat is CSV naar JSON conversie?

CSV naar JSON conversie transformeert een plat, kommagescheiden tekstformaat naar een gestructureerde array van objecten, waarbij elke rij een JavaScript-object wordt met de kolomkoppen als sleutels. Het CSV-formaat heeft geen datatypes — alles is een string. JSON voegt structuur, nesting en expliciete types toe (getallen, booleans, null). Deze conversie is de eerste stap in vrijwel elke datapipeline die begint met een spreadsheet-export, een dump van een oud systeem of een door de gebruiker geüpload bestand. De onderliggende data blijft hetzelfde; het formaat verandert van positiegebaseerde kolommen naar benoemde eigenschappen.

Before · json
After · json
name,email,role,active
Jan de Vries,jdevries@nexuslabs.io,Engineering Lead,true
Emma Bakker,ebakker@nexuslabs.io,Product Manager,true
[
  {
    "name": "Jan de Vries",
    "email": "jdevries@nexuslabs.io",
    "role": "Engineering Lead",
    "active": "true"
  },
  {
    "name": "Emma Bakker",
    "email": "ebakker@nexuslabs.io",
    "role": "Product Manager",
    "active": "true"
  }
]

csvToJson() — Een herbruikbare conversiefunctie bouwen

De volledige CSV-naar-JSON-pipeline in JavaScript bestaat uit drie stappen: splits de CSV-string op regeleinde om rijen te krijgen, haal de headers op uit de eerste rij met split(','), en map elke resterende rij naar een gewoon JavaScript-object waarbij de sleutels afkomstig zijn uit de headers en de waarden uit de overeenkomende kolomposities. De laatste aanroep naar JSON.stringify() converteert die array van objecten naar een JSON-string. Hier is een minimale werkende versie:

JavaScript — minimale csvToJson
function csvToJson(csv) {
  const lines = csv.trim().split('\n')
  const headers = lines[0].split(',').map(h => h.trim())

  const rows = lines.slice(1)
    .filter(line => line.trim() !== '')
    .map(line => {
      const values = line.split(',')
      return Object.fromEntries(
        headers.map((header, i) => [header, values[i]?.trim()])
      )
    })

  return JSON.stringify(rows, null, 2)
}

const csv = `server,port,region,status
api-gateway,8080,eu-west-1,healthy
auth-service,8443,eu-west-1,degraded
payments-api,9090,eu-central-1,healthy`

console.log(csvToJson(csv))
// [
//   { "server": "api-gateway", "port": "8080", "region": "eu-west-1", "status": "healthy" },
//   { "server": "auth-service", "port": "8443", "region": "eu-west-1", "status": "degraded" },
//   { "server": "payments-api", "port": "9090", "region": "eu-central-1", "status": "healthy" }
// ]

Die functie verwerkt de basis: afsluitende regeleinden, lege regels, witruimte rondom waarden. Elk CSV-veld komt door als een string. Let op dat port gelijk is aan "8080" (een string), niet 8080 (een getal). Als je de juiste types in de JSON-uitvoer nodig hebt, moet je ze zelf omzetten. Hier is een uitgebreide versie met typedetectie:

JavaScript — csvToJson met typeconversie
function coerceValue(val) {
  if (val === undefined || val === '') return null
  if (val === 'true') return true
  if (val === 'false') return false
  if (val === 'null') return null
  const num = Number(val)
  if (!isNaN(num) && val.trim() !== '') return num
  return val
}

function csvToJson(csv, { coerce = false } = {}) {
  const lines = csv.trim().split('\n')
  const headers = lines[0].split(',').map(h => h.trim())

  const rows = lines.slice(1)
    .filter(line => line.trim() !== '')
    .map(line => {
      const values = line.split(',')
      return Object.fromEntries(
        headers.map((header, i) => [
          header,
          coerce ? coerceValue(values[i]?.trim()) : values[i]?.trim()
        ])
      )
    })

  return JSON.stringify(rows, null, 2)
}

const csv = `endpoint,port,max_connections,debug
/api/v2/orders,8443,500,true
/api/v2/health,8080,100,false`

console.log(csvToJson(csv, { coerce: true }))
// [
//   { "endpoint": "/api/v2/orders", "port": 8443, "max_connections": 500, "debug": true },
//   { "endpoint": "/api/v2/health", "port": 8080, "max_connections": 100, "debug": false }
// ]

De coerce vlag is opt-in omdat automatische typedetectie kan terugvuren — een veld zoals een postcode ("07302") verliest zijn voorloopnul wanneer het naar een getal wordt omgezet. Houd conversie standaard uit en schakel het alleen in wanneer je het schema beheerst. Kleine kanttekening: JSON.stringify() accepteert een derde space argument voor inspringing. Geef 2 voor twee spaties, 4 voor vier, of "\t" voor tabs. Laat het helemaal weg voor compacte uitvoer op één regel — handig wanneer je de JSON-string als een API-verzoekbody verzendt waarbij witruimte alleen bandbreedte verspilt.

Opmerking:Een onbewerkte CSV-string is geen JSON. Het rechtstreeks aanroepen van JSON.parse() op CSV-tekst gooit een SyntaxError. Je moet de CSV eerst naar JavaScript-objecten converteren met je csvToJson()-functie, die intern JSON.stringify() aanroept om de werkelijke JSON-string te produceren.

Omgaan met Maps, Dates en aangepaste objecten uit CSV-data

Niet elke CSV-conversie eindigt met een platte array van gewone objecten. Soms moet je een Map bouwen van header-waardeparen, datumstrings parsen naar Date-objecten, of berekende eigenschappen toevoegen voor serialisatie. JavaScript heeft een eigenaardigheid die mensen betrapt: Map-instanties serialiseren niet met JSON.stringify(). Je krijgt een leeg object. De oplossing is Object.fromEntries() om de Map terug te zetten naar een gewoon object voor het serialiseren.

De reden dat Map serialiseert naar {} is dat JSON.stringify() over de eigen enumereerbare eigenschappen van een object itereert. Een Map slaat zijn vermeldingen op in een intern slot, niet als enumereerbare eigenschappen op het object zelf, dus de serializer ziet een object zonder sleutels. Het Map-prototype mist ook een toJSON() methode, dat de hook is die JSON.stringify() als eerste aanroept op elke waarde voordat het beslist hoe het te serialiseren. Als een waarde toJSON() heeft, is de retourwaarde van de methode wat geserialiseerd wordt — niet het object zelf. Dit is waarom Date objecten correct serialiseren: Date.prototype.toJSON geeft een ISO 8601-string terug, zodat JSON.stringify(new Date()) een tijdstempel tussen aanhalingstekens produceert in plaats van een leeg object. Dit mechanisme begrijpen laat je hetzelfde gedrag definiëren op je eigen klassen — zoals getoond in het EmployeeRecord voorbeeld hieronder — om exact te bepalen welke CSV-afgeleide velden in de uiteindelijke JSON-uitvoer verschijnen.

Een Map naar JSON converteren

JavaScript — Map naar JSON via Object.fromEntries()
// Bouw een Map van CSV header→waardeparen
const headers = ['server', 'port', 'region']
const values = ['payments-api', '9090', 'eu-central-1']
const rowMap = new Map(headers.map((h, i) => [h, values[i]]))

// Map serialiseert NIET direct
console.log(JSON.stringify(rowMap))
// "{}"  — leeg object, data verloren!

// Eerst omzetten naar gewoon object
const rowObj = Object.fromEntries(rowMap)
console.log(JSON.stringify(rowObj, null, 2))
// {
//   "server": "payments-api",
//   "port": "9090",
//   "region": "eu-central-1"
// }

Datumstrings en toJSON()

CSV-datumvelden komen aan als strings. Als je ze tijdens de verwerking naar Date-objecten parst, serialiseren die Dates correct omdat Date een ingebouwde toJSON() methode heeft die een ISO 8601-string retourneert. Je kunt ook aangepaste toJSON() definiëren op je eigen klassen om te bepalen welke CSV-kolommen in de geserialiseerde uitvoer verschijnen — bijvoorbeeld het weglaten van interne trackingvelden zoals _rowIndex.

JavaScript — toJSON() voor aangepaste serialisatie
class EmployeeRecord {
  constructor(csvRow) {
    this._rowIndex = csvRow._rowIndex  // intern, niet voor JSON
    this.employeeId = csvRow.employee_id
    this.name = csvRow.name
    this.hiredAt = new Date(csvRow.hired_date)
    this.salary = Number(csvRow.salary)
  }

  toJSON() {
    // Alleen de velden blootstellen die we in de JSON-uitvoer willen
    return {
      employee_id: this.employeeId,
      name: this.name,
      hired_at: this.hiredAt,  // Date.toJSON() → ISO string automatisch
      salary: this.salary,
    }
  }
}

const csvRow = {
  _rowIndex: 42,
  employee_id: 'EMP-2847',
  name: 'Jan de Vries',
  hired_date: '2024-03-15',
  salary: '128000',
}

const record = new EmployeeRecord(csvRow)
console.log(JSON.stringify(record, null, 2))
// {
//   "employee_id": "EMP-2847",
//   "name": "Jan de Vries",
//   "hired_at": "2024-03-15T00:00:00.000Z",
//   "salary": 128000
// }
// Opmerking: _rowIndex is uitgesloten, salary is een getal, datum is ISO-formaat

Reviver voor datum-deserialisatie

Na het schrijven van CSV-afgeleide JSON naar een bestand of het versturen over het netwerk geeft JSON.parse() je gewone objecten terug — de Date-objecten worden weer strings. Gebruik een reviver-functie om ISO 8601-strings tijdens het parsen terug te zetten naar Date-objecten:

JavaScript — reviver om Date-objecten te reconstrueren
const jsonString = '{"employee_id":"EMP-2847","name":"Jan de Vries","hired_at":"2024-03-15T00:00:00.000Z","salary":128000}'

const isoDatePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/

const parsed = JSON.parse(jsonString, (key, value) => {
  if (typeof value === 'string' && isoDatePattern.test(value)) {
    return new Date(value)
  }
  return value
})

console.log(parsed.hired_at instanceof Date)  // true
console.log(parsed.hired_at.getFullYear())    // 2024
Waarschuwing:JSON.stringify() geeft undefined terug (geen string) voor waarden die functies, Symbols of undefined-eigenschappen bevatten. Als je CSV-afgeleide objecten per ongeluk een undefined-waarde oppikken van een ontbrekende kolom, verdwijnt die eigenschap stil uit de JSON-uitvoer. Gebruik altijd null als standaardwaarde voor ontbrekende waarden.

JSON.stringify() parameters referentie

De functiehandtekening is JSON.stringify(value, replacer?, space?). De replacer en space argumenten zijn beide optioneel — geef null voor de replacer wanneer je alleen inspringing nodig hebt.

Parameter
Type
Standaard
Beschrijving
value
any
(verplicht)
De JavaScript-waarde om te serialiseren — object, array, string, getal, boolean of null
replacer
Function | Array | null
undefined
Filtert of transformeert waarden tijdens serialisatie. Een array vormt een whitelist van eigenschapsnamen; een functie ontvangt (key, value)-paren
space
number | string
undefined
Inspringing: getal 0–10 voor spaties, string (bijv. "\t") voor aangepaste inspringing. Weglaten voor compacte uitvoer op één regel

JSON.parse() parameters:

Parameter
Type
Standaard
Beschrijving
text
string
(verplicht)
De JSON-string om te parsen — moet geldige JSON zijn, anders wordt een SyntaxError gegenereerd
reviver
Function | undefined
undefined
Wordt aangeroepen voor elk sleutel-waardepaar. De retourwaarde vervangt het origineel; undefined retourneren verwijdert de eigenschap

JSON.parse() — De JSON-uitvoer verwerken

Zodra je een JSON-string hebt van csvToJson(), is de volgende stap gewoonlijk deze terug te parsen naar een actieve JavaScript-array voor filteren, mappen of doorgeven aan een API. Het verschil tussen een JSON-string (typeof === "string") en een JavaScript-object is belangrijk. Je kunt .filter() niet aanroepen of [0].name benaderen op een string — je hebt eerst JSON.parse() nodig. Deze rondreis (stringify dan parse) werkt ook als een validatietechniek: als je CSV-conversie iets heeft geproduceerd dat geen geldige JSON is, zal parse een foutmelding geven. Het optionele reviver-argument laat je elk sleutel-waardepaar transformeren tijdens het parsen — handig voor het herstellen van Date-objecten uit ISO-strings of het hernoemen van sleutels zonder een aparte stap.

JavaScript — JSON-uitvoer parsen en rijen bevragen
const csv = `endpoint,method,avg_latency_ms,error_rate
/api/v2/orders,POST,342,0.02
/api/v2/health,GET,12,0.00
/api/v2/payments,POST,890,0.15
/api/v2/users,GET,45,0.01`

// Stap 1: CSV omzetten naar JSON-string
const jsonString = csvToJson(csv, { coerce: true })

// Stap 2: terugparsen naar JavaScript-array
const endpoints = JSON.parse(jsonString)

// Controleer of het een array is
console.log(Array.isArray(endpoints))  // true

// Filter endpoints met hoge latentie
const slow = endpoints.filter(ep => ep.avg_latency_ms > 200)
console.log(slow.map(ep => ep.endpoint))
// ["/api/v2/orders", "/api/v2/payments"]

// Destructureer de eerste rij
const [first, ...rest] = endpoints
console.log(first.endpoint)  // "/api/v2/orders"
console.log(rest.length)     // 3

Een veilige wrapper voor JSON.parse() is handig bij het valideren van conversie-uitvoer voor verdere verwerking. Als de CSV-conversie om welke reden dan ook misvormde JSON produceert (afgekapte invoer, coderingsfouten), vangt dit het op zonder te crashen:

JavaScript — veilige parse-wrapper
function safeParse(jsonString) {
  try {
    return { data: JSON.parse(jsonString), error: null }
  } catch (err) {
    return { data: null, error: err.message }
  }
}

// Geldige uitvoer
const result = safeParse(csvToJson(csv))
if (result.error) {
  console.error('CSV-conversie produceerde ongeldige JSON:', result.error)
} else {
  console.log(`${result.data.length} rijen geparsed`)
}

// Per ongeluk onbewerkte CSV doorgeven aan JSON.parse — dit mislukt
const bad = safeParse('name,email\nJan,jdevries@nexuslabs.io')
console.log(bad.error)  // "Unexpected token 'a', "name,email"... is not valid JSON"

Reviver voor sleutelhernoemen en validatie

De reviver-functie ontvangt elk sleutel-waardepaar tijdens het parsen, van de binnenste eigenschappen naar buiten. Het retourneren van undefined voor een sleutel verwijdert het volledig uit het resultaat; het retourneren van een andere waarde vervangt het. De reviver is handig voor het hernoemen van headers (camelCase naar snake_case), het verwijderen van interne velden of het controleren of vereiste kolommen bestaan. Het wordt als laatste aangeroepen met de root-waarde (lege string-sleutel), wat de plek is waar je een fout gooit als het resultaat geen array is.

JavaScript — reviver voor sleutelhernoemen en vormvalidatie
const jsonString = csvToJson(`employeeId,firstName,hiredDate
EMP-2847,Jan,2024-03-15
EMP-3012,Emma,2023-11-01`, { coerce: false })

const camelToSnake = str => str.replace(/[A-Z]/g, c => '_' + c.toLowerCase())

const employees = JSON.parse(jsonString, function(key, value) {
  // Root-waarde — valideer de vorm
  if (key === '') {
    if (!Array.isArray(value)) throw new Error('Verwachtte JSON-array van CSV')
    return value
  }
  // Hernoem camelCase-headersleutels naar snake_case
  if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
    return Object.fromEntries(
      Object.entries(value).map(([k, v]) => [camelToSnake(k), v])
    )
  }
  return value
})

console.log(employees[0])
// { employee_id: 'EMP-2847', first_name: 'Jan', hired_date: '2024-03-15' }

CSV converteren vanuit een bestand en API-respons

De twee plekken waar CSV-data in productie vandaan komt: bestanden op schijf en HTTP- responses. Beide scenario's vereisen foutafhandeling omdat de invoer extern en onbeheerst is.

CSV-bestand lezen, converteren, JSON schrijven

Node.js 18+ — bestandsconversie
import { readFileSync, writeFileSync } from 'node:fs'

function csvToJsonFromFile(inputPath, outputPath) {
  let csvText
  try {
    csvText = readFileSync(inputPath, 'utf8')
  } catch (err) {
    throw new Error(`Kan ${inputPath} niet lezen: ${err.message}`)
  }

  const lines = csvText.trim().split('\n')
  if (lines.length < 2) {
    throw new Error(`${inputPath} heeft geen datarijen (slechts ${lines.length} regel)`)
  }

  const headers = lines[0].split(',').map(h => h.trim())
  const rows = lines.slice(1)
    .filter(line => line.trim() !== '')
    .map(line => {
      const values = line.split(',')
      return Object.fromEntries(headers.map((h, i) => [h, values[i]?.trim()]))
    })

  const jsonOutput = JSON.stringify(rows, null, 2)
  writeFileSync(outputPath, jsonOutput, 'utf8')
  console.log(`${rows.length} rijen geconverteerd → ${outputPath}`)
  return rows
}

// Gebruik
const data = csvToJsonFromFile('inventaris.csv', 'inventaris.json')
console.log(data[0])
// { sku: "WDG-2847", warehouse: "eu-west-1", quantity: "150", ... }

CSV ophalen van een API-endpoint

Node.js 18+ — API-respons conversie
async function fetchCsvAsJson(url) {
  const response = await fetch(url)
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`)
  }

  const contentType = response.headers.get('content-type') || ''
  if (!contentType.includes('text/csv') && !contentType.includes('text/plain')) {
    console.warn(`Onverwacht content-type: ${contentType}`)
  }

  const csvText = await response.text()
  const lines = csvText.trim().split('\n')
  const headers = lines[0].split(',').map(h => h.trim())
  const rows = lines.slice(1)
    .filter(line => line.trim() !== '')
    .map(line => {
      const values = line.split(',')
      return Object.fromEntries(headers.map((h, i) => [h, values[i]?.trim()]))
    })

  return rows
}

// Voorbeeld: wisselkoers CSV ophalen van een dataprovider
try {
  const rates = await fetchCsvAsJson('https://data.ecb.internal/rates/daily.csv')
  console.log(JSON.stringify(rates.slice(0, 3), null, 2))
  // Verstuur als JSON naar downstream-service
  await fetch('https://api.internal/v2/rates', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ data: rates }),
  })
} catch (err) {
  console.error('Koerssynchronisatie mislukt:', err.message)
}
Opmerking:Het replacer-argument in JSON.stringify() laat je specifieke kolommen uit de CSV whitelisten. Geef een array van headernamen door om alleen die velden op te nemen: JSON.stringify(rows, ['name', 'email', 'department']). Eigenschappen die niet in de array staan, worden stil uitgesloten van de uitvoer.

CSV naar JSON conversie via de opdrachtregel

Node.js kan inline scripts uitvoeren, en er zijn speciale CLI-tools die CSV-naar-JSON- conversie afhandelen zonder een script te hoeven schrijven.

bash — Node.js one-liner
# Pipe CSV naar een Node.js inline script
cat servers.csv | node -e "
  const lines = require('fs').readFileSync('/dev/stdin','utf8').trim().split('\n');
  const h = lines[0].split(',');
  const rows = lines.slice(1).map(l => Object.fromEntries(h.map((k,i) => [k.trim(), l.split(',')[i]?.trim()])));
  console.log(JSON.stringify(rows, null, 2));
"
bash — Miller (mlr) voor CSV naar JSON
# Miller is een Zwitsers zakmes voor gestructureerde data
# Installeer: brew install miller (macOS) of apt install miller (Debian/Ubuntu)
mlr --icsv --ojson cat inventaris.csv

# Rijen filteren tijdens conversie
mlr --icsv --ojson filter '$quantity > 100' inventaris.csv

# Specifieke kolommen selecteren
mlr --icsv --ojson cut -f sku,warehouse,quantity inventaris.csv
bash — csvtojson CLI
# Globaal installeren
npm install -g csvtojson

# Bestand converteren
csvtojson servers.csv > servers.json

# Pipe vanuit stdin
cat exports/q1-metrics.csv | csvtojson > q1-metrics.json

Voor grote bestanden is Miller gewoonlijk de betere keuze boven csvtojson. Miller is geïmplementeerd in C en verwerkt CSV als een stream zonder het volledige bestand in het geheugen te laden, wat betekent dat het multi-gigabyte exports verwerkt bij constant geheugengebruik. Het ondersteunt ook in-place bewerkingen op veldniveau — kolommen hernoemen, waarden casten, rijen filteren — voordat de data JSON wordt, zodat je een tweestaps parse-dan-transformeer-pipeline vermijdt. csvtojson daarentegen draait in Node.js en is handiger wanneer de rest van je toolchain JavaScript is: je kunt de uitvoer direct in Node.js streams pipen, het als library importeren, of de colParser API gebruiken voor per-kolom typeconversie in code. Geef de voorkeur aan Miller voor ruwe doorvoer en shell-pipelines; geef de voorkeur aan csvtojson wanneer je nauwe integratie met een Node.js-applicatie nodig hebt.

Opmerking:jq parseert CSV niet van nature. Als je jq in de pipeline nodig hebt, converteer dan eerst naar JSON met csvtojson of mlr, en pipe daarna de JSON-uitvoer naar jq voor filteren en transformeren.

Krachtig alternatief — PapaParse

De handmatige split(',') aanpak faalt op echte CSV-bestanden. Aangehaalde velden met komma's, ingesloten regeleinden, geëscapete dubbele aanhalingstekens — dit alles breekt een eenvoudige splitter. PapaParse is de library waar ik naar grijp wanneer de CSV van een onbekende bron komt. Het verwerkt elk RFC 4180-randgeval, detecteert scheidingstekens automatisch en werkt in zowel Node.js als browsers.

bash — PapaParse installeren
npm install papaparse
JavaScript — PapaParse met typeconversie
import Papa from 'papaparse'

const csv = `product,description,price,in_stock
"Widget, Groot","Een premium widget met ""extra"" functies",29.99,true
Bout Set,Standaard M8 boutset,4.50,true
"Pakking Set","Inclusief pakking, afdichting en O-ring",12.75,false`

const { data, errors, meta } = Papa.parse(csv, {
  header: true,
  dynamicTyping: true,     // auto-converteert getallen en booleans
  skipEmptyLines: true,
  transformHeader: h => h.trim().toLowerCase().replace(/\s+/g, '_'),
})

if (errors.length > 0) {
  console.error('Parseerfouten:', errors)
}

console.log(JSON.stringify(data, null, 2))
// [
//   {
//     "product": "Widget, Groot",
//     "description": "Een premium widget met \"extra\" functies",
//     "price": 29.99,
//     "in_stock": true
//   },
//   ...
// ]
console.log(`${data.length} rijen geparsed, scheidingsteken: "${meta.delimiter}"`)

De dynamicTyping optie van PapaParse doet de typeconversie automatisch — getallen worden getallen, "true"/"false" worden booleans. De transformHeader callback normaliseert kolomnamen naar snake_case, waardoor je geen last hebt van inconsistente headers van verschillende CSV-exports. Voor snelle conversies zonder parseCode te schrijven verwerkt de CSV naar JSON converter dit alles in de browser.

Terminaluitvoer met syntaxiskleuring

Een grote JSON-array naar de terminal dumpen vermoeit je ogen snel. Syntaxiskleuring toevoegen aan de uitvoer maakt het leesbaar tijdens het debuggen en ontwikkelen. Het cli-highlight pakket kleurt JSON-uitvoer in Node.js-terminals.

bash — cli-highlight installeren
npm install cli-highlight
JavaScript — gekleurde JSON-uitvoer in terminal
import { highlight } from 'cli-highlight'

// Na CSV naar JSON-array conversie
const jsonOutput = JSON.stringify(rows, null, 2)

// Afdrukken met syntaxiskleuring
console.log(highlight(jsonOutput, { language: 'json' }))
// Sleutels, strings, getallen en booleans krijgen elk aparte kleuren

Gekleurde uitvoer is zijn waarde waard wanneer je een groot conversieresultaat interactief inspecteert. JSON-sleutels, stringwaarden, getallen en booleans krijgen elk aparte ANSI- kleuren, wat het gemakkelijk maakt om een veld te herkennen waarvan het type fout is — bijvoorbeeld een poortnummer dat 8080 zou moeten zijn maar als string wordt gemarkeerd omdat conversie uitgeschakeld was. Dit is vooral handig bij het debuggen van CSV-bestanden die zijn geëxporteerd vanuit spreadsheettools waarbij kolomtypes inconsistent zijn over rijen. Zonder kleur betekent het scannen van 50 rijen JSON voor één verkeerd getypt veld elke waarde afzonderlijk lezen. Met kleur springt een string-gekleurde getal er direct uit.

Waarschuwing:Syntaxiskleuring voegt ANSI-escapecodes toe aan de uitvoer. Gebruik het niet bij het schrijven van JSON naar een bestand, pipen naar een ander programma, of versturen als een API-responsbody — de escapecodes zouden de JSON beschadigen. Gebruik kleuring alleen voor terminalweergave.

Werken met grote CSV-bestanden

Een CSV-bestand van 500 MB in een string laden met readFileSync() verbruikt veel geheugen en kan je proces laten crashen. Stroomt de CSV voor grote bestanden regel voor regel en geef JSON-objecten door zodra ze binnenkomen. Het csv-parse pakket (onderdeel van het csv-ecosysteem op npm) biedt een streaming parser die werkt met Node.js-streams.

CSV streamen naar NDJSON met csv-parse

NDJSON (Newline-Delimited JSON) is een formaat waarbij elke regel van het uitvoerbestand een op zichzelf staand JSON-object is. In tegenstelling tot een enkele grote JSON-array — die vereist dat het volledige bestand in het geheugen staat voordat je kunt beginnen met lezen — kunnen NDJSON-bestanden regel voor regel worden verwerkt. Dit maakt NDJSON ideaal voor grote datasets die worden verwerkt door logverwerkers, stream-pipelines of databases met bulk-import API's. Het csv-parse pakket geeft één JavaScript-object per CSV-rij in objectmodus door, zodat je het direct kunt pipen naar een transformstream die \n toevoegt na elk JSON.stringify(row).

Node.js 18+ — streaming CSV naar NDJSON
import { createReadStream, createWriteStream } from 'node:fs'
import { parse } from 'csv-parse'
import { Transform } from 'node:stream'
import { pipeline } from 'node:stream/promises'

// Elk CSV-rij-object transformeren naar een JSON-regel
const toNdjson = new Transform({
  objectMode: true,
  transform(record, encoding, callback) {
    callback(null, JSON.stringify(record) + '\n')
  },
})

await pipeline(
  createReadStream('telemetrie-2026-03.csv'),
  parse({
    columns: true,       // gebruik eerste rij als headers
    skip_empty_lines: true,
    trim: true,
    cast: true,          // auto-converteer getallen en booleans
  }),
  toNdjson,
  createWriteStream('telemetrie-2026-03.ndjson')
)

console.log('Streaming conversie voltooid')
// Elke regel in het uitvoerbestand is één JSON-object:
// {"timestamp":"2026-03-15T08:22:00Z","service":"gateway","latency_ms":42,"status":200}
// {"timestamp":"2026-03-15T08:22:01Z","service":"auth","latency_ms":156,"status":401}
// ...

PapaParse streaming voor browser en Node.js

De streamingmodus van PapaParse gebruikt een step callback die eenmaal per rij wordt aangeroepen in plaats van alle rijen in het geheugen te verzamelen. Je geeft het een Node.js ReadStream (in Node.js) of een File object (in de browser) en PapaParse verwerkt de chunking intern. Geen stream-pipeline nodig — alleen een callback. Gebruik het wanneer je RFC 4180-naleving nodig hebt zonder csv-parse te importeren.

Node.js — PapaParse streaming groot bestand
import Papa from 'papaparse'
import { createReadStream } from 'node:fs'

let rowCount = 0
const errors = []

const fileStream = createReadStream('magazijn-inventaris.csv')

Papa.parse(fileStream, {
  header: true,
  dynamicTyping: true,
  step(result) {
    // Verwerk één rij tegelijk — constant geheugengebruik
    rowCount++
    if (result.data.quantity === 0) {
      errors.push(`Rij ${rowCount}: ${result.data.sku} is uitverkocht`)
    }
  },
  complete() {
    console.log(`${rowCount} rijen verwerkt`)
    if (errors.length > 0) {
      console.log(`Problemen gevonden: ${errors.length}`)
      errors.forEach(e => console.log(`  ${e}`))
    }
  },
  error(err) {
    console.error('Parsen mislukt:', err.message)
  },
})
Opmerking:Schakel over naar streaming wanneer je CSV-bestand groter is dan 50 MB of wanneer je een onbegrensde invoer verwerkt (WebSocket-feed, server-sent events, gepiped stdin). Het NDJSON-formaat (één JSON-object per regel) is vaak een beter uitvoerformaat dan een grote JSON-array voor grote datasets — het kan regel voor regel worden verwerkt zonder het volledige bestand in het geheugen te laden.

Veelgemaakte fouten

JSON.parse() rechtstreeks aanroepen op een CSV-string

Probleem: CSV is geen JSON. Het doorgeven van een onbewerkte CSV-string aan JSON.parse() gooit een SyntaxError omdat komma's en regeleinden geen geldige JSON-syntaxis zijn.

Oplossing: Parseer de CSV eerst naar JavaScript-objecten met split() of een library, gebruik dan JSON.stringify() om JSON te produceren. Roep JSON.parse() alleen aan op strings die al geldige JSON zijn.

Before · JavaScript
After · JavaScript
const csv = 'name,email\nJan de Vries,jdevries@nexuslabs.io'
const data = JSON.parse(csv)
// SyntaxError: Unexpected token 'a'
const csv = 'name,email\nJan de Vries,jdevries@nexuslabs.io'
const lines = csv.trim().split('\n')
const headers = lines[0].split(',')
const rows = lines.slice(1).map(line =>
  Object.fromEntries(headers.map((h, i) => [h, line.split(',')[i]]))
)
const json = JSON.stringify(rows, null, 2)  // geldige JSON-string
toString() gebruiken in plaats van JSON.stringify()

Probleem: toString() aanroepen op een JavaScript-object geeft de nutteloze string '[object Object]' terug in plaats van de werkelijke data. Dit vernietigt je CSV-naar-JSON-uitvoer stil.

Oplossing: Gebruik altijd JSON.stringify() om JavaScript-objecten naar JSON-strings te converteren. toString() bestaat voor primitief-naar-string-conversie, niet voor serialisatie.

Before · JavaScript
After · JavaScript
const row = { server: 'api-gateway', port: 8080 }
const output = row.toString()
// "[object Object]"  — data is weg
const row = { server: 'api-gateway', port: 8080 }
const output = JSON.stringify(row, null, 2)
// '{"server":"api-gateway","port":8080}'
Splitsen op komma zonder aangehaalde velden te verwerken

Probleem: Een eenvoudige split(",") breekt wanneer CSV-waarden komma's bevatten in aangehaalde velden: "Widget, Groot" wordt twee afzonderlijke waarden in plaats van één.

Oplossing: Gebruik PapaParse of csv-parse voor CSV-data die je niet volledig beheerst. Als je handmatig moet parsen, implementeer een toestandsmachine-parser die bijhoudt of de huidige positie binnen een aangehaald veld is.

Before · JavaScript
After · JavaScript
const line = '"Widget, Groot","Premium kwaliteit",29.99'
const values = line.split(',')
// ["\"Widget", " Groot\"", "\"Premium kwaliteit\"", "29.99"]
// 4 waarden in plaats van 3 — eerste veld verkeerd gesplitst
import Papa from 'papaparse'
const { data } = Papa.parse('"Widget, Groot","Premium kwaliteit",29.99')
// data[0] = ["Widget, Groot", "Premium kwaliteit", "29.99"]
// 3 waarden, correct geparsed
Vergeten dat alle CSV-waarden strings zijn

Probleem: Zonder typeconversie blijft port: "8080" een string in JSON in plaats van een getal. Downstream-systemen die numerieke types verwachten, wijzen de data af of verwerken het verkeerd.

Oplossing: Pas expliciete typeconversie toe tijdens de mappingstap, of gebruik PapaParse met dynamicTyping: true. Wees altijd bewust over welke velden numeriek moeten zijn.

Before · JavaScript
After · JavaScript
const row = { port: '8443', debug: 'true', workers: '4' }
JSON.stringify(row)
// {"port":"8443","debug":"true","workers":"4"}  — alles strings
const row = {
  port: Number('8443'),           // 8443
  debug: 'true' === 'true',      // true
  workers: Number('4'),           // 4
}
JSON.stringify(row)
// {"port":8443,"debug":true,"workers":4}  — correcte types

Handmatig parsen vs. libraries — Snelle vergelijking

Methode
Opgemaakte uitvoer
Geldige JSON
Aangepaste types
Streaming
Installatie vereist
JSON.stringify()
✓ (met space)
✓ via toJSON()/replacer
Nee (ingebouwd)
JSON.parse()
N/A (parsen)
✓ (valideert)
✓ via reviver
Nee (ingebouwd)
csv-parse (Node.js)
✗ (geeft objecten)
✗ (geen JSON)
npm install
PapaParse
✗ (geeft objecten)
✗ (geen JSON)
npm install
csvtojson
✓ via colParser
npm install
jq (CLI)
N/A
Systeeminstallatie
Miller (CLI)
N/A
Systeeminstallatie

Voor snelle scripts waarbij je het CSV-formaat beheert en weet dat er geen aangehaalde velden zijn, werkt de ingebouwde split() + JSON.stringify() aanpak en heeft het nul afhankelijkheden. Voor productiesystemen die door gebruikers geüploade CSV-bestanden verwerken, gebruik PapaParse in de browser of csv-parse in Node.js — beide verwerken RFC 4180 correct en ondersteunen streaming. Het csvtojson pakket is het enige dat JSON direct uitvoert, waarbij zowel parsen als serialisatie in één aanroep worden afgehandeld. Wanneer je de snelste weg van plakken tot resultaat nodig hebt, verwerkt de CSV naar JSON converter alles in de browser zonder enige setup.

Veelgestelde vragen

Hoe zet ik CSV om naar JSON in JavaScript zonder een library?

Splits de CSV-string op regeleinde om rijen te krijgen, haal de headers op uit de eerste rij met split(","), en map de overige rijen naar objecten met die headers als sleutels. Eindig met JSON.stringify(array, null, 2) voor een opgemaakte JSON-string. Deze aanpak werkt goed voor eenvoudige CSV-bestanden waarvan je het formaat beheerst en weet dat er geen aangehaalde velden of ingesloten komma's zijn. Voor data afkomstig van spreadsheet-exports of systemen van derden zullen aangehaalde velden en meerregelige waarden een eenvoudige splitter breken — gebruik in die gevallen PapaParse of csv-parse. Voor zeer kleine bestanden die in de browser worden verwerkt, is deze aanpak zonder afhankelijkheden ideaal.

JavaScript
const csv = `name,email,department
Jan de Vries,jdevries@nexuslabs.io,Engineering
Emma Bakker,ebakker@nexuslabs.io,Product`

const lines = csv.trim().split('\n')
const headers = lines[0].split(',')
const rows = lines.slice(1).map(line => {
  const values = line.split(',')
  return Object.fromEntries(headers.map((h, i) => [h.trim(), values[i]?.trim()]))
})

console.log(JSON.stringify(rows, null, 2))
// [
//   { "name": "Jan de Vries", "email": "jdevries@nexuslabs.io", "department": "Engineering" },
//   { "name": "Emma Bakker", "email": "ebakker@nexuslabs.io", "department": "Product" }
// ]

Wat is het verschil tussen JSON.stringify() en toString() voor objecten?

toString() op een gewoon object geeft de nutteloze string "[object Object]" terug — het zegt niets over de werkelijke data. JSON.stringify() produceert een geldige JSON-string met alle sleutels en waarden correct geserialiseerd, inclusief geneste objecten en arrays. Gebruik altijd JSON.stringify() als je een JavaScript-object (zoals een rij afgeleid van CSV) wilt omzetten naar een JSON-string. Om de bewerking om te keren — JavaScript-objecten reconstrueren vanuit een JSON-string — gebruik je JSON.parse(), de exacte inverse van JSON.stringify(). Deze twee functies vormen samen een volledige rondreis: stringify om data op te slaan of te versturen, parse om het te verwerken.

JavaScript
const row = { name: 'Jan de Vries', role: 'Engineer' }

console.log(row.toString())       // "[object Object]"
console.log(JSON.stringify(row))   // '{"name":"Jan de Vries","role":"Engineer"}'

Hoe ga ik om met CSV-velden die komma's of aanhalingstekens bevatten?

RFC 4180 specificeert dat velden met komma's, regeleinden of dubbele aanhalingstekens tussen dubbele aanhalingstekens moeten staan, waarbij ingesloten aanhalingstekens worden verdubbeld ("" in een aangehaald veld staat voor een enkel letterlijk aanhalingsteken). Een handmatige split(",") breekt op zulke bestanden — de veldgrens is niet langer een gewone komma. Gebruik PapaParse of csv-parse voor productiedata, of schrijf een toestandsmachine-parser die bijhoudt of je binnen een aangehaald veld zit. Een correcte toestandsmachine zelf schrijven is verrassend lastig: je moet aanhalingstekens aan het begin van een veld, ingesloten aanhalingstekens halverwege, regeleinden binnen aangehaalde velden en verschillende regeleindeconventies (CRLF vs LF) verwerken. Gebruik voor alles buiten speelgoed-CSV-data een goed geteste library.

JavaScript
// PapaParse verwerkt RFC 4180 correct
import Papa from 'papaparse'

const csv = `product,description,price
"Widget, Groot","Een groot ""widget""",29.99
Bout,Standaardbout,1.50`

const { data } = Papa.parse(csv, { header: true })
console.log(JSON.stringify(data, null, 2))
// description-veld bevat correct: Een groot "widget"

Kan ik CSV direct in de browser naar JSON omzetten?

Ja. Zowel JSON.stringify() als JSON.parse() zijn ingebouwd in elke browser-engine. Voor de CSV-parseerstap kun je voor eenvoudige bestanden splitsen op regeleinde en komma, of PapaParse via een CDN opnemen (het heeft geen Node.js-afhankelijkheden). De volledige conversie vindt client-side plaats zonder een server-roundtrip, wat handig is voor bestandsprivacy — de onbewerkte CSV-data verlaat de machine van de gebruiker nooit. Wanneer een gebruiker een CSV-bestand uploadt via een <input type="file">-element, geeft de file.text()-methode van de File API een Promise terug die oplost naar de bestandsinhoud als string, die je dan aan je conversiefunctie kunt doorgeven. Dit maakt volledig in-browser CSV-naar-JSON-conversie praktisch voor dashboards, ontwikkelaarstools en elke app die geüploade data zonder een backend moet verwerken.

JavaScript
// Browser: gebruiker uploadt een CSV-bestand
const fileInput = document.querySelector('input[type="file"]')
fileInput.addEventListener('change', async (event) => {
  const file = event.target.files[0]
  const text = await file.text()
  const lines = text.trim().split('\n')
  const headers = lines[0].split(',')
  const rows = lines.slice(1).map(line =>
    Object.fromEntries(headers.map((h, i) => [h.trim(), line.split(',')[i]?.trim()]))
  )
  console.log(JSON.stringify(rows, null, 2))
})

Hoe parseer ik numerieke en boolean waarden uit CSV in plaats van alles als strings te houden?

CSV heeft geen typesysteem — elk veld is een string. Je moet waarden omzetten tijdens de mappingstap. Controleer op numerieke patronen met Number() of parseFloat(), zet "true"/"false" om naar booleans en behandel lege strings als null. Wees voorzichtig met velden die eruitzien als getallen maar als strings moeten blijven: postcodes zoals "1234AB" verliezen hun formaat wanneer ze met Number() worden omgezet, en telefoonnummers of productcodes met cijfers zijn vergelijkbaar kwetsbaar. De csvtojson-library doet automatische typeconversie via de colParser-optie, waarmee je per-kolom conversiefuncties kunt opgeven en de automatische detectie voor probleemkolommen kunt overschrijven. De dynamicTyping-optie van PapaParse past dezelfde conversie globaal toe op alle kolommen.

JavaScript
function coerceValue(val) {
  if (val === '') return null
  if (val === 'true') return true
  if (val === 'false') return false
  const num = Number(val)
  if (!isNaN(num) && val.trim() !== '') return num
  return val
}

// Toepassen tijdens CSV-naar-object-mapping
const row = { port: coerceValue('8443'), debug: coerceValue('true'), host: coerceValue('api.internal') }
// { port: 8443, debug: true, host: "api.internal" }

Hoe schrijf ik CSV-naar-JSON-uitvoer naar een bestand in Node.js?

Gebruik fs.writeFileSync() met de uitvoer van JSON.stringify(). Het derde argument van JSON.stringify bepaalt de inspringing — geef 2 voor twee spaties of "\t" voor tabs. Om het bestand terug te lezen, gebruik je JSON.parse(fs.readFileSync(path, "utf8")), wat de actieve JavaScript-array van objecten reconstrueert. Als je het bestand schrijft in een asynchrone context (binnen een async-functie of op het hoogste niveau van een ES-module), gebruik dan bij voorkeur fs.promises.writeFile() om te voorkomen dat de event loop blokkeert terwijl het bestand wordt geschreven. Voor grote JSON-uitvoer van meer dan een paar megabytes, overweeg een JSON-stream naar een WriteStream te pipen in plaats van de volledige string in het geheugen op te bouwen voordat je schrijft.

JavaScript
import { writeFileSync, readFileSync } from 'node:fs'

// Schrijven
const jsonOutput = JSON.stringify(rows, null, 2)
writeFileSync('medewerkers.json', jsonOutput, 'utf8')

// Teruggelezen
const parsed = JSON.parse(readFileSync('medewerkers.json', 'utf8'))
console.log(Array.isArray(parsed))  // true
console.log(parsed[0].name)         // "Jan de Vries"

Gerelateerde tools

Ook beschikbaar in:Python
AC
Alex ChenFront-end & Node.js Developer

Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.

SL
Sophie LaurentTechnisch beoordelaar

Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.