CSV to JSON JavaScript — Converter + Code Examples
Nutze das kostenlose CSV to JSON direkt im Browser – keine Installation erforderlich.
CSV to JSON online testen →Die meisten CSV-Daten, denen man begegnet, kommen als flacher String aus einem Datei-Upload, einem Datenbankexport oder einer API, die noch das Format der 1970er Jahre spricht. Um CSV zu JSON in JavaScript zu konvertieren, braucht man zwei Dinge, die die Sprache kostenlos mitliefert: String-Splitting zum Parsen der Zeilen und JSON.stringify() zur Serialisierung des Ergebnisses. Für die Grundlagen sind keine npm-Pakete erforderlich — dieser Leitfaden deckt die gesamte Pipeline ab: von einer wiederverwendbaren csvToJson() Hilfsfunktion bis hin zu PapaParse und Node.js-Datei-I/O. Für schnelle Konvertierungen ohne Code erledigt das Online-CSV-zu-JSON-Konverter sofort. Alle Beispiele richten sich an Node.js 18+ und moderne Browser.
- ✓CSV nach Zeilenumbruch aufteilen, Header aus Zeile 0 extrahieren, verbleibende Zeilen auf Objekte abbilden, dann JSON.stringify(array, null, 2) für formatierte Ausgabe.
- ✓JSON.stringify() erzeugt einen String; JSON.parse() wandelt ihn zurück in ein aktives JavaScript-Array — vor der Weiterverarbeitung wissen, welches man hat.
- ✓Map-Instanzen werden nicht automatisch zu JSON serialisiert — zuerst Object.fromEntries(map) aufrufen.
- ✓Für CSV mit Feldern in Anführungszeichen, Kommas innerhalb von Werten oder Zeilenumbrüchen in Zellen PapaParse oder csv-parse statt manueller Aufteilung verwenden.
- ✓csvtojson (npm) behandelt Typumwandlung, Streaming und RFC-4180-Grenzfälle in einem einzigen Aufruf.
Was ist CSV-zu-JSON-Konvertierung?
CSV-zu-JSON-Konvertierung transformiert ein flaches, kommageteiltes Textformat in ein strukturiertes Array von Objekten, bei dem jede Zeile zu einem JavaScript-Objekt mit den Spaltenüberschriften als Schlüssel wird. Das CSV-Format kennt keine Datentypen — alles ist ein String. JSON fügt Struktur, Verschachtelung und explizite Typen hinzu (Zahlen, Booleans, null). Diese Konvertierung ist der erste Schritt in fast jeder Datenpipeline, die mit einem Tabellenkalkulationsexport, einem Legacy-System-Export oder einer vom Benutzer hochgeladenen Datei beginnt. Die zugrunde liegenden Daten bleiben gleich; das Format wechselt von positionsbasierten Spalten zu benannten Eigenschaften.
name,email,role,active Anna Schmidt,aschmidt@nexuslabs.io,Engineering Lead,true Thomas Müller,tmueller@nexuslabs.io,Product Manager,true
[
{
"name": "Anna Schmidt",
"email": "aschmidt@nexuslabs.io",
"role": "Engineering Lead",
"active": "true"
},
{
"name": "Thomas Müller",
"email": "tmueller@nexuslabs.io",
"role": "Product Manager",
"active": "true"
}
]csvToJson() — Eine wiederverwendbare Konvertierungsfunktion erstellen
Die vollständige CSV-zu-JSON-Pipeline in JavaScript gliedert sich in drei Schritte: den CSV-String nach Zeilenumbruch aufteilen, um Zeilen zu erhalten, Header aus der ersten Zeile mit split(',') extrahieren, dann jede weitere Zeile auf ein einfaches JavaScript-Objekt abbilden, bei dem die Schlüssel aus den Headern und die Werte aus den entsprechenden Spaltenpositionen stammen. Der abschließende Aufruf von JSON.stringify() wandelt dieses Array von Objekten in einen JSON-String um. Hier ist eine minimale funktionsfähige Version:
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-central-1,healthy
auth-service,8443,eu-west-1,degraded
payments-api,9090,ap-south-1,healthy`
console.log(csvToJson(csv))
// [
// { "server": "api-gateway", "port": "8080", "region": "eu-central-1", "status": "healthy" },
// { "server": "auth-service", "port": "8443", "region": "eu-west-1", "status": "degraded" },
// { "server": "payments-api", "port": "9090", "region": "ap-south-1", "status": "healthy" }
// ]Diese Funktion behandelt die Grundlagen: abschließende Zeilenumbrüche, leere Zeilen, Leerzeichen um Werte. Jedes CSV-Feld kommt als String durch. Beachten: port ist "8080" (ein String), nicht 8080 (eine Zahl). Wenn korrekte Typen in der JSON-Ausgabe benötigt werden, müssen diese selbst umgewandelt werden. Hier ist eine erweiterte Version mit Typerkennung:
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 }
// ]Das coerce Flag ist opt-in, weil automatische Typerkennung nach hinten losgehen kann — ein Feld wie eine Postleitzahl ("07302") verliert seine führende Null, wenn es in eine Zahl umgewandelt wird. Typumwandlung standardmäßig deaktiviert lassen und nur aktivieren, wenn das Schema bekannt ist. Kurze Anmerkung: JSON.stringify() akzeptiert ein drittes space Argument für die Einrückung. 2 für zwei Leerzeichen übergeben, 4 für vier, oder "\t" für Tabs. Ganz weglassen für kompakte einzeilige Ausgabe — nützlich beim Senden des JSON-Strings als API-Request-Body, wo Leerzeichen nur Bandbreite verschwenden.
JSON.parse() direkt auf CSV-Text wirft einen SyntaxError. Das CSV muss zunächst mit der csvToJson()-Funktion in JavaScript-Objekte umgewandelt werden, die intern JSON.stringify() aufruft, um den eigentlichen JSON-String zu erzeugen.Maps, Dates und benutzerdefinierte Objekte aus CSV-Daten verarbeiten
Nicht jede CSV-Konvertierung endet mit einem flachen Array einfacher Objekte. Manchmal muss eine Map aus Header-Wert-Paaren aufgebaut, Datums-Strings in Date-Objekte geparst oder berechnete Eigenschaften vor der Serialisierung angehängt werden. JavaScript hat eine Eigenart, über die man gerne stolpert: Map-Instanzen werden mit JSON.stringify() nicht serialisiert. Es kommt ein leeres Objekt heraus. Die Lösung ist Object.fromEntries(), um die Map vor dem Stringifying zurück in ein einfaches Objekt zu konvertieren.
Der Grund, warum Map zu {} serialisiert wird, ist, dass JSON.stringify() über die eigenen aufzählbaren Eigenschaften eines Objekts iteriert. Eine Map speichert ihre Einträge in einem internen Slot, nicht als aufzählbare Eigenschaften des Objekts selbst, sodass der Serialisierer ein Objekt ohne Schlüssel sieht. Dem Map-Prototyp fehlt auch eine toJSON()-Methode, die den Hook darstellt, den JSON.stringify() zuerst auf jeden Wert aufruft, bevor er entscheidet, wie er ihn serialisiert. Wenn ein Wert toJSON() hat, wird der Rückgabewert der Methode serialisiert — nicht das Objekt selbst. Deshalb werden Date-Objekte korrekt serialisiert: Date.prototype.toJSON gibt einen ISO-8601-String zurück, sodass JSON.stringify(new Date()) einen Zeitstempel in Anführungszeichen erzeugt, anstatt eines leeren Objekts. Das Verständnis dieses Hooks ermöglicht es, dasselbe Verhalten in eigenen Klassen zu definieren — wie im EmployeeRecord-Beispiel unten gezeigt — um genau zu steuern, welche CSV-abgeleiteten Felder in der endgültigen JSON-Ausgabe erscheinen.
Eine Map in JSON umwandeln
// Map aus CSV-Header→Wert-Paaren aufbauen
const headers = ['server', 'port', 'region']
const values = ['payments-api', '9090', 'ap-south-1']
const rowMap = new Map(headers.map((h, i) => [h, values[i]]))
// Map wird NICHT direkt serialisiert
console.log(JSON.stringify(rowMap))
// "{}" — leeres Objekt, Daten verloren!
// Zuerst in einfaches Objekt umwandeln
const rowObj = Object.fromEntries(rowMap)
console.log(JSON.stringify(rowObj, null, 2))
// {
// "server": "payments-api",
// "port": "9090",
// "region": "ap-south-1"
// }Datums-Strings und toJSON()
CSV-Datumsfelder kommen als Strings an. Wenn sie während der Verarbeitung in Date-Objekte geparst werden, serialisieren diese Dates korrekt, weil Date eine eingebaute toJSON()-Methode hat, die einen ISO-8601-String zurückgibt. Eigene toJSON()-Methoden können auch in eigenen Klassen definiert werden, um zu steuern, welche CSV-Spalten in der serialisierten Ausgabe erscheinen — zum Beispiel interne Tracking-Felder wie _rowIndex auszuschließen.
class EmployeeRecord {
constructor(csvRow) {
this._rowIndex = csvRow._rowIndex // intern, nicht für JSON
this.employeeId = csvRow.employee_id
this.name = csvRow.name
this.hiredAt = new Date(csvRow.hired_date)
this.salary = Number(csvRow.salary)
}
toJSON() {
// Nur die Felder exponieren, die in der JSON-Ausgabe erscheinen sollen
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: 'Anna Schmidt',
hired_date: '2024-03-15',
salary: '128000',
}
const record = new EmployeeRecord(csvRow)
console.log(JSON.stringify(record, null, 2))
// {
// "employee_id": "EMP-2847",
// "name": "Anna Schmidt",
// "hired_at": "2024-03-15T00:00:00.000Z",
// "salary": 128000
// }
// Hinweis: _rowIndex ist ausgeschlossen, salary ist eine Zahl, Datum ist im ISO-FormatReviver für Datums-Deserialisierung
Nachdem CSV-abgeleitetes JSON in eine Datei geschrieben oder über das Netzwerk gesendet wurde, gibt JSON.parse() einfache Objekte zurück — die Date-Objekte werden wieder zu Strings. Eine Reviver-Funktion verwenden, um ISO-8601-Strings beim Parsen zurück in Date-Objekte zu konvertieren:
const jsonString = '{"employee_id":"EMP-2847","name":"Anna Schmidt","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()) // 2024JSON.stringify() gibt undefined (keinen String) für Werte zurück, die Funktionen, Symbols oder undefined-Eigenschaften enthalten. Wenn CSV-abgeleitete Objekte versehentlich einen undefined-Wert aus einer fehlenden Spalte aufnehmen, verschwindet diese Eigenschaft stillschweigend aus der JSON-Ausgabe. Fehlende Werte immer als null behandeln.JSON.stringify() Parameterreferenz
Die Funktionssignatur lautet JSON.stringify(value, replacer?, space?). Die Argumente replacer und space sind beide optional — für den replacer null übergeben, wenn nur Einrückung benötigt wird.
JSON.parse() Parameter:
JSON.parse() — Die JSON-Ausgabe verwenden
Sobald ein JSON-String aus csvToJson() vorliegt, ist der nächste Schritt meist, ihn zurück in ein aktives JavaScript-Array zu parsen, um es zu filtern, abzubilden oder an eine API zu übergeben. Der Unterschied zwischen einem JSON-String (typeof === "string") und einem JavaScript-Objekt ist entscheidend. Auf einem String kann nicht .filter() aufgerufen oder [0].name zugegriffen werden — dafür wird zuerst JSON.parse() benötigt. Dieser Kreislauf (stringify dann parse) funktioniert auch als Validierungstechnik: Wenn die CSV-Konvertierung etwas erzeugt hat, das kein gültiges JSON ist, wirft parse einen Fehler. Das optionale reviver-Argument ermöglicht die Transformation jedes Schlüssel-Wert-Paares beim Parsen — nützlich zum Wiederherstellen von Date-Objekten aus ISO-Strings oder zum Umbenennen von Schlüsseln ohne einen separaten Durchlauf.
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`
// Schritt 1: CSV in JSON-String konvertieren
const jsonString = csvToJson(csv, { coerce: true })
// Schritt 2: zurück in JavaScript-Array parsen
const endpoints = JSON.parse(jsonString)
// Prüfen, ob es ein Array ist
console.log(Array.isArray(endpoints)) // true
// Endpunkte mit hoher Latenz filtern
const slow = endpoints.filter(ep => ep.avg_latency_ms > 200)
console.log(slow.map(ep => ep.endpoint))
// ["/api/v2/orders", "/api/v2/payments"]
// Erste Zeile destrukturieren
const [first, ...rest] = endpoints
console.log(first.endpoint) // "/api/v2/orders"
console.log(rest.length) // 3Ein sicherer Wrapper für JSON.parse() ist nützlich, wenn die Konvertierungsausgabe vor der Weiterverarbeitung validiert werden soll. Wenn die CSV-Konvertierung aus irgendeinem Grund fehlerhaftes JSON erzeugt (abgeschnittene Eingabe, Kodierungsfehler), fängt dieser Wrapper es ab, ohne abzustürzen:
function safeParse(jsonString) {
try {
return { data: JSON.parse(jsonString), error: null }
} catch (err) {
return { data: null, error: err.message }
}
}
// Gültige Ausgabe
const result = safeParse(csvToJson(csv))
if (result.error) {
console.error('CSV-Konvertierung hat ungültiges JSON erzeugt:', result.error)
} else {
console.log(`${result.data.length} Zeilen geparst`)
}
// Versehentliches Übergeben von rohem CSV an JSON.parse — dies schlägt fehl
const bad = safeParse('name,email\nAnna,aschmidt@nexuslabs.io')
console.log(bad.error) // "Unexpected token 'a', "name,email"... is not valid JSON"Reviver für Schlüsselumbenennungen und Validierung
Die Reviver-Funktion erhält jedes Schlüssel-Wert-Paar beim Parsen, von den innersten Eigenschaften nach außen. Das Zurückgeben von undefined für einen Schlüssel entfernt ihn vollständig aus dem Ergebnis; das Zurückgeben eines anderen Werts ersetzt ihn. Der Reviver ist nützlich zum Umbenennen von Headern (camelCase zu snake_case), zum Entfernen interner Felder oder zum Prüfen, ob erforderliche Spalten vorhanden sind. Er wird zuletzt mit dem Root-Wert aufgerufen (leerer String-Schlüssel), wo ein Fehler geworfen werden kann, wenn das Ergebnis kein Array ist.
const jsonString = csvToJson(`employeeId,firstName,hiredDate
EMP-2847,Anna,2024-03-15
EMP-3012,Thomas,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-Wert — Form validieren
if (key === '') {
if (!Array.isArray(value)) throw new Error('Erwartetes JSON-Array aus CSV')
return value
}
// camelCase-Header-Schlüssel in snake_case umbenennen
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: 'Anna', hired_date: '2024-03-15' }CSV aus Datei und API-Antwort konvertieren
Die zwei Orte, von denen CSV-Daten in der Produktion tatsächlich kommen: Dateien auf dem Laufwerk und HTTP-Antworten. Beide Szenarien benötigen Fehlerbehandlung, weil die Eingabe extern und unkontrolliert ist.
CSV-Datei lesen, konvertieren, JSON schreiben
import { readFileSync, writeFileSync } from 'node:fs'
function csvToJsonFromFile(inputPath, outputPath) {
let csvText
try {
csvText = readFileSync(inputPath, 'utf8')
} catch (err) {
throw new Error(`Fehler beim Lesen von ${inputPath}: ${err.message}`)
}
const lines = csvText.trim().split('\n')
if (lines.length < 2) {
throw new Error(`${inputPath} hat keine Datenzeilen (nur ${lines.length} Zeile)`)
}
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} Zeilen konvertiert → ${outputPath}`)
return rows
}
// Verwendung
const data = csvToJsonFromFile('inventar.csv', 'inventar.json')
console.log(data[0])
// { sku: "WDG-2847", warehouse: "eu-central-1", quantity: "150", ... }CSV von einem API-Endpunkt abrufen
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(`Unerwarteter 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
}
// Beispiel: Wechselkurs-CSV von einem Datenanbieter abrufen
try {
const rates = await fetchCsvAsJson('https://data.ecb.internal/rates/daily.csv')
console.log(JSON.stringify(rates.slice(0, 3), null, 2))
// Als JSON an nachgelagerten Dienst senden
await fetch('https://api.internal/v2/rates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: rates }),
})
} catch (err) {
console.error('Kurs-Synchronisation fehlgeschlagen:', err.message)
}JSON.stringify() ermöglicht es, bestimmte Spalten aus dem CSV auf eine Allowlist zu setzen. Ein Array von Header-Namen übergeben, um nur diese Felder einzuschließen: JSON.stringify(rows, ['name', 'email', 'department']). Nicht im Array enthaltene Eigenschaften werden stillschweigend aus der Ausgabe ausgeschlossen.CSV-zu-JSON-Konvertierung über die Kommandozeile
Node.js kann Inline-Skripte ausführen, und es gibt dedizierte CLI-Tools, die CSV-zu-JSON-Konvertierung ohne das Schreiben eines Skripts ermöglichen.
# CSV an ein Node.js-Inline-Skript pipen
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));
"# Miller ist ein Schweizer Taschenmesser für strukturierte Daten # Installation: brew install miller (macOS) oder apt install miller (Debian/Ubuntu) mlr --icsv --ojson cat inventar.csv # Zeilen bei der Konvertierung filtern mlr --icsv --ojson filter '$quantity > 100' inventar.csv # Bestimmte Spalten auswählen mlr --icsv --ojson cut -f sku,warehouse,quantity inventar.csv
# Global installieren npm install -g csvtojson # Datei konvertieren csvtojson servers.csv > servers.json # Von stdin pipen cat exports/q1-metriken.csv | csvtojson > q1-metriken.json
Für große Dateien ist Miller meist die bessere Wahl gegenüber csvtojson. Miller ist in C implementiert und verarbeitet CSV als Stream, ohne die gesamte Datei in den Speicher zu laden, sodass es mehrgigabyte-große Exporte mit konstantem Speicherverbrauch verarbeitet. Es unterstützt auch feldbasierte Operationen im laufenden Betrieb — Spalten umbenennen, Werte typenkonvertieren, Zeilen filtern — bevor die Daten überhaupt zu JSON werden, sodass eine zweistufige Parse-dann-Transform-Pipeline vermieden wird. csvtojson hingegen läuft in Node.js und ist praktischer, wenn der Rest der Toolchain JavaScript ist: die Ausgabe kann direkt in Node-Streams geleitet, als Bibliothek importiert oder die colParser-API für spaltenweise Typumwandlung im Code verwendet werden. Miller für rohen Durchsatz und Shell-Pipelines bevorzugen; csvtojson bevorzugen, wenn eine enge Integration mit einer Node.js-Anwendung benötigt wird.
jq parst CSV nicht nativ. Wenn jq in der Pipeline benötigt wird, zuerst mit csvtojson oder mlr in JSON konvertieren, dann die JSON-Ausgabe zur Filterung und Transformation an jq pipen.Hochleistungsalternative — PapaParse
Der manuelle split(',')-Ansatz schlägt bei realen CSV-Dateien fehl. Felder in Anführungszeichen mit Kommas, eingebettete Zeilenumbrüche, escapte doppelte Anführungszeichen — all das bricht einen naiven Splitter. PapaParse ist die Bibliothek der Wahl, wenn CSV aus einer unbekannten Quelle kommt. Sie behandelt jeden RFC-4180-Grenzfall, erkennt Trennzeichen automatisch und funktioniert sowohl in Node.js als auch in Browsern.
npm install papaparse
import Papa from 'papaparse'
const csv = `produkt,beschreibung,preis,auf_lager
"Widget, Groß","Ein Premium-Widget mit ""extra""-Funktionen",29.99,true
Schraubenset,Standard-M8-Schraubenset,4.50,true
"Dichtungsset","Enthält Dichtung, Siegel und O-Ring",12.75,false`
const { data, errors, meta } = Papa.parse(csv, {
header: true,
dynamicTyping: true, // wandelt Zahlen und Booleans automatisch um
skipEmptyLines: true,
transformHeader: h => h.trim().toLowerCase().replace(/\s+/g, '_'),
})
if (errors.length > 0) {
console.error('Parse-Fehler:', errors)
}
console.log(JSON.stringify(data, null, 2))
// [
// {
// "produkt": "Widget, Groß",
// "beschreibung": "Ein Premium-Widget mit \"extra\"-Funktionen",
// "preis": 29.99,
// "auf_lager": true
// },
// ...
// ]
console.log(`${data.length} Zeilen geparst, Trennzeichen: "${meta.delimiter}"`)PapaParses dynamicTyping-Option führt die Typumwandlung automatisch durch — Zahlen werden zu Zahlen, "true"/"false" werden zu Booleans. Der transformHeader-Callback normalisiert Spaltennamen auf snake_case, was das Umgehen mit inkonsistenten Headern aus verschiedenen CSV-Exporten erspart. Für schnelle Konvertierungen ohne Schreiben von Parsing-Code erledigt das CSV-zu-JSON-Konverter alles im Browser.
Terminal-Ausgabe mit Syntaxhervorhebung
Ein großes JSON-Array im Terminal auszugeben macht die Augen schnell müde. Das Hinzufügen von Syntaxhervorhebung zur Ausgabe macht sie beim Debuggen und in der Entwicklung lesbar. Das cli-highlight-Paket koloriert JSON-Ausgaben in Node.js-Terminals.
npm install cli-highlight
import { highlight } from 'cli-highlight'
// Nach der Konvertierung von CSV in JSON-Array
const jsonOutput = JSON.stringify(rows, null, 2)
// Mit Syntaxhervorhebung ausgeben
console.log(highlight(jsonOutput, { language: 'json' }))
// Schlüssel, Strings, Zahlen und Booleans erhalten jeweils eigene FarbenKolorierte Ausgaben zahlen sich bei der interaktiven Inspektion eines großen Konvertierungsergebnisses aus. JSON-Schlüssel, String-Werte, Zahlen und Booleans erhalten jeweils eigene ANSI-Farben, sodass ein Feld mit falschem Typ leicht zu erkennen ist — zum Beispiel eine Portnummer, die 8080 sein sollte, aber als String hervorgehoben wird, weil die Typumwandlung deaktiviert war. Das ist besonders nützlich beim Debuggen von CSV-Dateien aus Tabellenkalkulations-Tools, bei denen Spaltentypen über Zeilen inkonsistent sind. Ohne Farbe bedeutet das Durchsuchen von 50 Zeilen JSON nach einem einzigen falsch eingegebenen Feld, jeden Wert einzeln zu lesen. Mit Farbe fällt ein als String gefärbter Wert sofort auf.
Mit großen CSV-Dateien arbeiten
Eine 500-MB-CSV-Datei mit readFileSync() in einen String zu laden wird den Speicher belasten und möglicherweise den Prozess zum Absturz bringen. Für große Dateien das CSV zeilenweise streamen und JSON-Objekte ausgeben, sobald sie ankommen. Das csv-parse-Paket (Teil des csv-Ökosystems auf npm) bietet einen Streaming-Parser, der mit Node.js-Streams funktioniert.
CSV mit csv-parse zu NDJSON streamen
NDJSON (Newline-Delimited JSON) ist ein Format, bei dem jede Zeile der Ausgabedatei ein eigenständiges JSON-Objekt ist. Im Gegensatz zu einem einzelnen großen JSON-Array — das die gesamte Datei im Speicher erfordert, bevor mit dem Lesen begonnen werden kann — können NDJSON-Dateien zeilenweise verarbeitet werden. Das macht NDJSON ideal für große Datensätze, die von Log-Prozessoren, Stream-Pipelines oder Datenbanken mit Bulk-Import-APIs verarbeitet werden sollen. Das csv-parse-Paket gibt im Object-Mode ein JavaScript-Objekt pro CSV-Zeile aus, sodass es direkt in einen Transform-Stream geleitet werden kann, der nach jedem JSON.stringify(row) ein \n anhängt.
import { createReadStream, createWriteStream } from 'node:fs'
import { parse } from 'csv-parse'
import { Transform } from 'node:stream'
import { pipeline } from 'node:stream/promises'
// Jedes CSV-Zeilenobjekt in eine JSON-Zeile transformieren
const toNdjson = new Transform({
objectMode: true,
transform(record, encoding, callback) {
callback(null, JSON.stringify(record) + '\n')
},
})
await pipeline(
createReadStream('telemetry-2026-03.csv'),
parse({
columns: true, // erste Zeile als Header verwenden
skip_empty_lines: true,
trim: true,
cast: true, // Zahlen und Booleans automatisch konvertieren
}),
toNdjson,
createWriteStream('telemetry-2026-03.ndjson')
)
console.log('Streaming-Konvertierung abgeschlossen')
// Jede Zeile in der Ausgabedatei ist ein JSON-Objekt:
// {"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 für Browser und Node.js
PapaParses Streaming-Modus verwendet einen step-Callback, der einmal pro Zeile ausgelöst wird, anstatt alle Zeilen im Speicher zu sammeln. Ein Node.js ReadStream (in Node.js) oder ein File-Objekt (im Browser) wird übergeben und PapaParse übernimmt das Chunking intern. Keine Stream-Pipeline zum Verdrahten — nur ein Callback. Verwenden, wenn RFC-4180-Konformität ohne csv-parse benötigt wird.
import Papa from 'papaparse'
import { createReadStream } from 'node:fs'
let rowCount = 0
const errors = []
const fileStream = createReadStream('lager-inventar.csv')
Papa.parse(fileStream, {
header: true,
dynamicTyping: true,
step(result) {
// Eine Zeile nach der anderen verarbeiten — konstanter Speicher
rowCount++
if (result.data.quantity === 0) {
errors.push(`Zeile ${rowCount}: ${result.data.sku} ist nicht vorrätig`)
}
},
complete() {
console.log(`${rowCount} Zeilen verarbeitet`)
if (errors.length > 0) {
console.log(`Gefundene Probleme: ${errors.length}`)
errors.forEach(e => console.log(` ${e}`))
}
},
error(err) {
console.error('Parse fehlgeschlagen:', err.message)
},
})Häufige Fehler
Problem: CSV ist kein JSON. Einen rohen CSV-String an JSON.parse() zu übergeben wirft einen SyntaxError, weil Kommas und Zeilenumbrüche keine gültige JSON-Syntax sind.
Lösung: Das CSV zuerst mit split() oder einer Bibliothek in JavaScript-Objekte parsen, dann JSON.stringify() verwenden, um JSON zu erzeugen. JSON.parse() nur auf Strings aufrufen, die bereits gültiges JSON sind.
const csv = 'name,email\nAnna Schmidt,aschmidt@nexuslabs.io' const data = JSON.parse(csv) // SyntaxError: Unexpected token 'a'
const csv = 'name,email\nAnna Schmidt,aschmidt@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) // gültiger JSON-StringProblem: toString() auf einem JavaScript-Objekt aufzurufen gibt den nutzlosen String '[object Object]' zurück anstatt der tatsächlichen Daten. Das zerstört stillschweigend die CSV-zu-JSON-Ausgabe.
Lösung: Immer JSON.stringify() verwenden, um JavaScript-Objekte in JSON-Strings umzuwandeln. toString() existiert für die Primitive-zu-String-Koersion, nicht für die Serialisierung.
const row = { server: 'api-gateway', port: 8080 }
const output = row.toString()
// "[object Object]" — Daten verlorenconst row = { server: 'api-gateway', port: 8080 }
const output = JSON.stringify(row, null, 2)
// '{"server":"api-gateway","port":8080}'Problem: Ein naives split(",") schlägt fehl, wenn CSV-Werte Kommas innerhalb von Feldern in Anführungszeichen enthalten: "Widget, Groß" wird zu zwei separaten Werten statt einem.
Lösung: PapaParse oder csv-parse für jegliche CSV-Daten verwenden, die nicht vollständig kontrolliert werden. Wenn manuell geparst werden muss, einen State-Machine-Parser implementieren, der verfolgt, ob die aktuelle Position innerhalb eines Feldes mit Anführungszeichen liegt.
const line = '"Widget, Groß","Premium Qualität",29.99'
const values = line.split(',')
// ["\"Widget", " Groß\"", "\"Premium Qualität\"", "29.99"]
// 4 Werte statt 3 — erstes Feld falsch aufgeteiltimport Papa from 'papaparse'
const { data } = Papa.parse('"Widget, Groß","Premium Qualität",29.99')
// data[0] = ["Widget, Groß", "Premium Qualität", "29.99"]
// 3 Werte, korrekt geparstProblem: Ohne Typumwandlung bleibt port: "8080" als String in JSON statt als Zahl. Nachgelagerte Systeme, die numerische Typen erwarten, lehnen die Daten ab oder verarbeiten sie falsch.
Lösung: Explizite Typumwandlung beim Mapping-Schritt anwenden, oder PapaParse mit dynamicTyping: true verwenden. Immer bewusst entscheiden, welche Felder numerisch sein sollen.
const row = { port: '8443', debug: 'true', workers: '4' }
JSON.stringify(row)
// {"port":"8443","debug":"true","workers":"4"} — alles Stringsconst row = {
port: Number('8443'), // 8443
debug: 'true' === 'true', // true
workers: Number('4'), // 4
}
JSON.stringify(row)
// {"port":8443,"debug":true,"workers":4} — korrekte TypenManuelles Parsing vs. Bibliotheken — Kurzvergleich
Für schnelle Skripte, bei denen das CSV-Format bekannt ist und keine Felder mit Anführungszeichen vorkommen, funktioniert der eingebaute split() + JSON.stringify()-Ansatz und erfordert null Abhängigkeiten. Für Produktionssysteme, die vom Benutzer hochgeladene CSV-Dateien verarbeiten, PapaParse im Browser oder csv-parse in Node.js verwenden — beide behandeln RFC 4180 korrekt und unterstützen Streaming. Das csvtojson-Paket ist das einzige, das JSON direkt ausgibt und sowohl Parsing als auch Serialisierung in einem einzigen Aufruf erledigt. Wenn der schnellste Weg von Einfügen zu Ergebnis benötigt wird, erledigt der CSV-zu-JSON-Konverter alles im Browser ohne jede Einrichtung.
Häufig gestellte Fragen
Wie konvertiere ich CSV zu JSON in JavaScript ohne eine Bibliothek?
Den CSV-String per Zeilenumbruch aufteilen, um Zeilen zu erhalten, Header aus der ersten Zeile mit split(",") extrahieren und die restlichen Zeilen auf Objekte abbilden, die durch diese Header als Schlüssel indiziert sind. Abschließend JSON.stringify(array, null, 2) aufrufen, um einen formatierten JSON-String zu erzeugen. Dieser Ansatz funktioniert gut für einfache CSV-Dateien, bei denen das Format bekannt ist und keine Felder mit Anführungszeichen oder eingebetteten Kommas vorkommen. Für Daten aus Tabellenkalkulations-Exporten oder Fremdsystemen können Felder mit Anführungszeichen und mehrzeilige Werte einen naiven Splitter zum Scheitern bringen — in solchen Fällen PapaParse oder csv-parse verwenden. Für sehr kleine, im Browser verarbeitete Dateien ist dieser Zero-Dependency-Ansatz ideal.
const csv = `name,email,department
Anna Schmidt,aschmidt@nexuslabs.io,Engineering
Thomas Müller,tmueller@nexuslabs.io,Produkt`
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": "Anna Schmidt", "email": "aschmidt@nexuslabs.io", "department": "Engineering" },
// { "name": "Thomas Müller", "email": "tmueller@nexuslabs.io", "department": "Produkt" }
// ]Was ist der Unterschied zwischen JSON.stringify() und toString() bei Objekten?
toString() auf einem normalen Objekt gibt den nutzlosen String "[object Object]" zurück — er enthält keine Informationen über die tatsächlichen Daten. JSON.stringify() erzeugt einen gültigen JSON-String mit allen Schlüsseln und Werten korrekt serialisiert, einschließlich verschachtelter Objekte und Arrays. JSON.stringify() immer verwenden, wenn ein JavaScript-Objekt (z. B. eine aus CSV abgeleitete Zeile) in einen JSON-String umgewandelt werden soll. Für die umgekehrte Operation — die Rekonstruktion aktiver JavaScript-Objekte aus einem JSON-String — JSON.parse() verwenden, das die genaue Umkehroperation zu JSON.stringify() ist. Diese beiden Funktionen bilden einen vollständigen Kreislauf: stringify zum Speichern oder Übertragen von Daten, parse zum Verarbeiten.
const row = { name: 'Anna Schmidt', role: 'Engineer' }
console.log(row.toString()) // "[object Object]"
console.log(JSON.stringify(row)) // '{"name":"Anna Schmidt","role":"Engineer"}'Wie gehe ich mit CSV-Feldern um, die Kommas oder Anführungszeichen enthalten?
RFC 4180 legt fest, dass Felder mit Kommas, Zeilenumbrüchen oder doppelten Anführungszeichen in doppelte Anführungszeichen eingeschlossen werden müssen, wobei eingebettete Anführungszeichen durch Verdopplung escapt werden ("" innerhalb eines Feldes in Anführungszeichen steht für ein einzelnes literales Anführungszeichen). Ein manuelles split(",") schlägt bei solchen Dateien fehl — die Feldgrenze ist kein einfaches Komma mehr. Für Produktionsdaten PapaParse oder csv-parse verwenden, oder einen State-Machine-Parser schreiben, der verfolgt, ob die aktuelle Position innerhalb eines Feldes mit Anführungszeichen liegt. Das korrekte Schreiben einer solchen State Machine ist überraschend anspruchsvoll: Anführungszeichen am Feldanfang, escapte Anführungszeichen innerhalb von Feldern, Zeilenumbrüche in Feldern mit Anführungszeichen und unterschiedliche Zeilenende-Konventionen (CRLF vs. LF) müssen alle behandelt werden. Für alles jenseits einfacher CSV-Daten eine bewährte Bibliothek verwenden.
// PapaParse verarbeitet RFC 4180 korrekt
import Papa from 'papaparse'
const csv = `produkt,beschreibung,preis
"Widget, Groß","Ein großes ""Widget""",29.99
Schraube,Standard-Schraube,1.50`
const { data } = Papa.parse(csv, { header: true })
console.log(JSON.stringify(data, null, 2))
// Das Beschreibungsfeld enthält korrekt: Ein großes "Widget"Kann ich CSV direkt im Browser zu JSON konvertieren?
Ja. Sowohl JSON.stringify() als auch JSON.parse() sind in jede Browser-Engine eingebaut. Für den CSV-Parsing-Schritt kann bei einfachen Dateien nach Zeilenumbruch und Komma aufgeteilt werden, oder PapaParse über ein CDN eingebunden werden (es hat keine Node.js-Abhängigkeiten). Die gesamte Konvertierung findet client-seitig ohne Server-Roundtrip statt, was für den Datenschutz nützlich ist — die rohen CSV-Daten verlassen nie den Rechner des Benutzers. Wenn ein Benutzer eine CSV-Datei über ein <input type="file">-Element hochlädt, gibt die file.text()-Methode der File API ein Promise zurück, das zum Dateiinhalt als String auflöst und dann an die Konvertierungsfunktion übergeben werden kann. Das macht vollständig browser-seitige CSV-zu-JSON-Konvertierung praktisch für Dashboards, Entwicklerwerkzeuge und jede App, die hochgeladene Daten ohne Backend verarbeiten muss.
// Browser: Benutzer lädt eine CSV-Datei hoch
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))
})Wie parse ich numerische und boolesche Werte aus CSV, statt alles als String zu behalten?
CSV hat kein Typsystem — jedes Feld ist ein String. Werte müssen beim Mapping-Schritt umgewandelt werden. Numerische Muster mit Number() oder parseFloat() prüfen, "true"/"false" in Booleans umwandeln und leere Strings als null behandeln. Vorsicht bei Feldern, die wie Zahlen aussehen, aber als Strings bleiben müssen: Postleitzahlen wie "07302" verlieren ihre führende Null, wenn sie mit Number() in eine Zahl umgewandelt werden, und Telefonnummern oder Produktcodes mit numerischen Zeichen sind ähnlich fehleranfällig. Die csvtojson-Bibliothek führt automatische Typumwandlung über ihre colParser-Option durch, mit der pro-Spalten-Konvertierungsfunktionen angegeben und die Auto-Erkennung für problematische Spalten überschrieben werden kann. Die dynamicTyping-Option von PapaParse wendet dieselbe Umwandlung global auf alle Spalten an.
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
}
// Beim CSV-zu-Objekt-Mapping anwenden
const row = { port: coerceValue('8443'), debug: coerceValue('true'), host: coerceValue('api.internal') }
// { port: 8443, debug: true, host: "api.internal" }Wie schreibe ich CSV-zu-JSON-Ausgaben in Node.js in eine Datei?
fs.writeFileSync() mit der JSON.stringify()-Ausgabe verwenden. Das dritte Argument von JSON.stringify steuert die Einrückung — 2 für zwei Leerzeichen oder "\t" für Tabs übergeben. Um die Datei wieder einzulesen, JSON.parse(fs.readFileSync(pfad, "utf8")) verwenden, das das aktive JavaScript-Array mit Objekten rekonstruiert. Wenn die Datei in einem asynchronen Kontext geschrieben wird (innerhalb einer async-Funktion oder auf oberster Ebene eines ES-Moduls), fs.promises.writeFile() bevorzugen, um das Blockieren der Event-Loop während des Schreibvorgangs zu vermeiden. Für große JSON-Ausgaben über einige Megabyte einen JSON-Stream an einen WriteStream pipen, anstatt den gesamten String im Speicher aufzubauen, bevor er geschrieben wird.
import { writeFileSync, readFileSync } from 'node:fs'
// Schreiben
const jsonOutput = JSON.stringify(rows, null, 2)
writeFileSync('mitarbeiter.json', jsonOutput, 'utf8')
// Wieder einlesen
const parsed = JSON.parse(readFileSync('mitarbeiter.json', 'utf8'))
console.log(Array.isArray(parsed)) // true
console.log(parsed[0].name) // "Anna Schmidt"Verwandte Tools
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.
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.