CSV to JSON JavaScript — Converter + Code Examples

·Front-end & Node.js Developer·Geprüft vonSophie Laurent·Veröffentlicht

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.

Before · json
After · json
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:

JavaScript — minimales 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-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:

JavaScript — csvToJson mit Typumwandlung
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.

Hinweis:Ein roher CSV-String ist kein JSON. Den Aufruf von 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

JavaScript — Map zu JSON via Object.fromEntries()
// 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.

JavaScript — toJSON() für benutzerdefinierte Serialisierung
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-Format

Reviver 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:

JavaScript — Reviver zur Rekonstruktion von Date-Objekten
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())    // 2024
Warnung:JSON.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.

Parameter
Typ
Standard
Beschreibung
value
any
(erforderlich)
Der zu serialisierende JavaScript-Wert — Objekt, Array, String, Zahl, Boolean oder null
replacer
Function | Array | null
undefined
Werte beim Serialisieren filtern oder transformieren. Array gibt erlaubte Eigenschaftsnamen vor; Funktion erhält (key, value)-Paare
space
number | string
undefined
Einrückung: Zahl 0–10 für Leerzeichen, String (z. B. "\t") für benutzerdefinierte Einrückung. Weglassen für kompakte einzeilige Ausgabe

JSON.parse() Parameter:

Parameter
Typ
Standard
Beschreibung
text
string
(erforderlich)
Der zu parsende JSON-String — muss gültiges JSON sein, sonst wird ein SyntaxError geworfen
reviver
Function | undefined
undefined
Wird für jedes Schlüssel-Wert-Paar aufgerufen. Der Rückgabewert ersetzt den ursprünglichen; undefined löscht die Eigenschaft

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.

JavaScript — JSON-Ausgabe parsen und Zeilen abfragen
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)     // 3

Ein 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:

JavaScript — sicherer Parse-Wrapper
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.

JavaScript — Reviver für Schlüsselumbenennungen und Formvalidierung
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

Node.js 18+ — Dateikonvertierung
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

Node.js 18+ — API-Antwort konvertieren
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)
}
Hinweis:Das replacer-Argument in 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.

bash — Node.js Einzeiler
# 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));
"
bash — Miller (mlr) für CSV zu JSON
# 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
bash — csvtojson CLI
# 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.

Hinweis: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.

bash — PapaParse installieren
npm install papaparse
JavaScript — PapaParse mit Typumwandlung
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.

bash — cli-highlight installieren
npm install cli-highlight
JavaScript — kolorierte JSON-Ausgabe im Terminal
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 Farben

Kolorierte 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.

Warnung:Syntaxhervorhebung fügt ANSI-Escape-Codes zur Ausgabe hinzu. Diese nicht verwenden, wenn JSON in eine Datei geschrieben, an ein anderes Programm gepipet oder als API-Response-Body gesendet wird — die Escape-Codes würden das JSON beschädigen. Hervorhebung nur für die Terminal-Anzeige verwenden.

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.

Node.js 18+ — CSV zu NDJSON streamen
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.

Node.js — PapaParse Streaming für große Dateien
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)
  },
})
Hinweis:Auf Streaming umschalten, wenn die CSV-Datei 50 MB überschreitet oder eine unbegrenzte Eingabe verarbeitet wird (WebSocket-Feed, Server-Sent Events, gepipeter stdin). Das NDJSON-Format (ein JSON-Objekt pro Zeile) ist für große Datensätze oft ein besseres Ausgabeformat als ein riesiges JSON-Array — es kann zeilenweise verarbeitet werden, ohne die gesamte Datei in den Speicher zu laden.

Häufige Fehler

JSON.parse() direkt auf einen CSV-String anwenden

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.

Before · JavaScript
After · JavaScript
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-String
toString() statt JSON.stringify() verwenden

Problem: 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.

Before · JavaScript
After · JavaScript
const row = { server: 'api-gateway', port: 8080 }
const output = row.toString()
// "[object Object]"  — Daten verloren
const row = { server: 'api-gateway', port: 8080 }
const output = JSON.stringify(row, null, 2)
// '{"server":"api-gateway","port":8080}'
Auf Komma splitten ohne Felder in Anführungszeichen zu berücksichtigen

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.

Before · JavaScript
After · JavaScript
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 aufgeteilt
import 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 geparst
Vergessen, dass alle CSV-Werte Strings sind

Problem: 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.

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}  — korrekte Typen

Manuelles Parsing vs. Bibliotheken — Kurzvergleich

Methode
Formatierte Ausgabe
Gültiges JSON
Benutzerdefinierte Typen
Streaming
Installation erforderlich
JSON.stringify()
✓ (mit space)
✓ via toJSON()/replacer
Nein (eingebaut)
JSON.parse()
N/A (Parsing)
✓ (validiert)
✓ via reviver
Nein (eingebaut)
csv-parse (Node.js)
✗ (gibt Objekte zurück)
✗ (kein JSON)
npm install
PapaParse
✗ (gibt Objekte zurück)
✗ (kein JSON)
npm install
csvtojson
✓ via colParser
npm install
jq (CLI)
N/A
System-Installation
Miller (CLI)
N/A
System-Installation

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.

JavaScript
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.

JavaScript
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.

JavaScript
// 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.

JavaScript
// 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.

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
}

// 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.

JavaScript
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

Auch verfügbar 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 LaurentTechnischer Prüfer

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.