CSV zu JSON: die fünf Fälle, an denen jeder Konverter scheitert
Veröffentlicht am 17.7.2026 · 13 Min. Lesezeit · Entwickler-Tools
Daniel Okonkwo — Front-end-Entwickler und Tech-Redakteur bei OneKitly
Web-Performance · Dateiformate
Anhand von 4 Quellen geprüft
CSV hat keinen Standard, nur RFC 4180 — ein Informational-RFC, das beschreibt, was die meisten Programme 2005 ohnehin taten, keine verbindliche Regel. Fünf Fälle trennen einen Parser, der funktioniert, von einem, der still Daten zerstört. Erstens ein Trennzeichen in einem zitierten Feld: name,city / Tom,"Paris, France" bleibt zweispaltig, und ein verdoppeltes Anführungszeichen im Feld kommt als eines zurück. Zweitens ein Zeilenumbruch in einem zitierten Feld: Der Parser liest bis zum schließenden Anführungszeichen, nicht bis zum Zeilenende, eine zweizeilige Adresse überlebt also als ein Wert. Drittens die Typen. Die Umwandlung ist standardmäßig aus; schaltet man sie ein, wird aus 1 die Zahl 1, während 0044, 1.0, 1e3, 2026-08-18 und 9007199254740993 Strings bleiben, denn eine Zelle wird nur umgewandelt, wenn die Zahl exakt so zurückgedruckt wird, wie sie ankam. true wird ein Boolean, TRUE nicht, weil JSON-Booleans kleingeschrieben sind, und null wird JSON-null — was am Tag überrascht, an dem ein Nachname Null lautet. Viertens doppelte Spaltennamen: Aus name,name,name werden name, name_2 und name_3 statt einer einzigen überlebenden Spalte, und ein leerer Spaltenname wird column2. Fünftens die Kodierung: Ein UTF-8-BOM wird entfernt, und der Browser schluckt BOMs für UTF-8 und UTF-16, bevor das Werkzeug den Text sieht — aber es gibt keine Kodierungsauswahl, also kommt ein Windows-1252-Export als Andr� an, und U+FFFD lässt sich nicht rückgängig machen. Zwei Fälle rettet er nicht: ein zitiertes Feld mit vorangestelltem Leerzeichen, Tom, "Paris, France", gilt nicht als zitiert, und eine Excel-Hinweiszeile sep=; wird als Kopfzeile verbraucht.
Trennzeichen in Anführungszeichen, eingebettete Zeilenumbrüche, mehrdeutige Typen, doppelte Spaltennamen und Kodierung. Jeder Fall lief durch den Konverter, und die exakte Ausgabe steht hier — auch die beiden, die er nicht rettet.
RFC 4180 ist eine Beschreibung, keine Regel
Alle zitieren RFC 4180, als wäre es der CSV-Standard. Der eigene Kopf des Dokuments sagt das Gegenteil: Es ist Informational, was in IETF-Sprache heißt, dass es überhaupt keinen Internet-Standard festlegt. Veröffentlicht wurde es 2005, um festzuhalten, was Programme ohnehin taten, und es sagt das über seinen eigenen Gegenstand: Regel 5 hält fest, dass manche Programme, darunter Microsoft Excel, gar keine Anführungszeichen verwenden. Das ist die Wurzel jedes Problems in diesem Artikel. Es gibt keine Instanz, die man anrufen könnte, wenn zwei Werkzeuge über dieselbe Datei uneins sind, denn keines verstößt gegen irgendetwas.
Das RFC definiert durchaus zwei Dinge, die helfen würden, und keines übersteht den Weg in eine Datei. Es definiert einen header-Parameter am Medientyp text/csv mit den Werten present und absent, damit dem Empfänger gesagt werden kann, ob die erste Zeile Spaltennamen enthält. Und es sagt, gängig sei US-ASCII, andere Zeichensätze würden über den charset-Parameter mitgeteilt. Beides sind MIME-Parameter: Sie leben an einer HTTP-Antwort oder einem Mailanhang, nicht in den Bytes. Speichere dieselben Daten als umsatz.csv, und beide Angaben sind weg. Deshalb hat jeder CSV-Leser der Welt ein Häkchen „erste Zeile ist Kopfzeile“, und deshalb muss die Kodierung geraten werden.
Fall 1 und 2 — Trennzeichen und Zeilenumbruch im zitierten Feld
Diese beiden sind derselbe Fehler in zwei Kostümen, und beide entstehen daraus, am rohen Zeichen zu trennen statt zu parsen. Ein Konverter, der text.split(",") macht, verwandelt Tom,"Paris, France" in drei Spalten, und jede Zeile darunter erbt die Extraspalte. Ein Konverter, der zuerst text.split("\n") macht, halbiert eine zweizeilige Adresse und erzeugt eine Zeile mit einem einzigen Feld. Die Abhilfe ist dieselbe: die Zeichenkette Zeichen für Zeichen durchlaufen, ein Flag mitführen, ob man in Anführungszeichen steht, und ein Trennzeichen oder einen Umbruch nur dann als strukturell behandeln, wenn das Flag aus ist.
Beide bestehen. name,address / Tom,"12 rue A\nParis" / Ann,"3 rue B" liefert genau zwei Objekte, das erste mit einer zweizeiligen Adresse. Ein verdoppeltes Anführungszeichen wird beim Einlesen entschärft, aus "He said ""hi"" loudly" wird also He said "hi" loudly. Eine Abweichung vom RFC sollte man kennen: Das Werkzeug normalisiert jedes CR LF vor dem Parsen zu LF, ein Zeilenumbruch, der im zitierten Feld ein CR LF war, verlässt den Konverter also als bloßes LF. Verloren geht nichts, aber wer den Rundlauf byteweise vergleicht, findet dort den Unterschied.
Der Fall, den er nicht rettet, ist der, zu dem das RFC ausdrücklich etwas sagt. Abschnitt 2.4 hält fest, dass Leerzeichen Teil des Feldes sind und nicht ignoriert werden dürfen: In Tom, "Paris, France" ist das erste Zeichen des Feldes ein Leerzeichen, und das folgende Anführungszeichen ist nur ein Zeichen, kein öffnendes Trennzeichen. Der Parser gibt dem RFC recht und erzeugt zwei kaputte Spalten, " Paris und France". Die meisten, die diese Zeile schreiben, meinten ein zitiertes Feld. Wenn dein Exporteur ein Leerzeichen hinter das Trennzeichen setzt, entferne es vor der Umwandlung, sonst ist die Zitierung reine Dekoration.
Fall 3 — Typen und der Rundlauftest, der deine Telefonnummern rettet
CSV hat keine Typen. Jede Zelle ist Text, und sobald du JSON erzeugst, musst du entscheiden, ob 1 die Zeichenkette "1" oder die Zahl 1 ist. Der Konverter entscheidet standardmäßig gar nichts: Die Umwandlung ist ein Schalter, und er steht auf aus, ein einfacher Lauf liefert also ein Array von Objekten, deren Werte durchweg Zeichenketten sind. Das ist die richtige Voreinstellung, denn eine Zeichenkette lässt sich immer zurückgewinnen, eine Zahl nicht.
Schalte um, und die Regel ist ein einziger Rundlauftest: Eine Zelle wird nur dann zur Zahl, wenn das Zurückdrucken dieser Zahl exakt die angekommenen Zeichen ergibt. Im Lauf wird aus 1 eine 1, aber 0044 bleibt "0044", weil Number("0044") als 44 druckt. 1.0 bleibt "1.0", weil es als 1 druckt. 1e3 bleibt "1e3", weil es als 1000 druckt. .5 und +1 bleiben aus demselben Grund Zeichenketten. Und 9007199254740993 bleibt eine Zeichenkette, weil der nächstliegende Double in JavaScript als 9007199254740992 druckt: Ein Konverter ohne diese Sicherung ändert stillschweigend die letzte Ziffer einer großen Kennung, und nichts weiter unten wird es dir je sagen.
Drei Dinge deckt der Rundlauftest nicht ab, weil sie stattdessen wörtlich verglichen werden. true und false werden zu Booleans, aber nur in Kleinschreibung: TRUE, True und FALSE bleiben Zeichenketten, was zählt, weil Excel Booleans groß schreibt und die französische und deutsche Oberfläche VRAI und WAHR schreiben. null wird zu JSON-null, und das ist eine echte Falle: Ein Textfeld mit dem Wert der vier Buchstaben null ist nicht dasselbe wie ein fehlender Wert, und nach der Umwandlung kannst du beides nicht mehr unterscheiden. Und mit Datumsangaben passiert gar nichts: 2026-08-18 bleibt die Zeichenkette "2026-08-18", und das ist die richtige Antwort, denn ein Konverter, der Daten parst, muss eine Zeitzone wählen und wird sie falsch wählen.
Fall 4 — doppelte Spaltennamen, leere Spaltennamen, ungleiche Zeilen
Ein CSV darf einen Spaltennamen wiederholen, ein JSON-Objekt nicht. Bei name,name,name über a,b,c schreibt die naive Umsetzung dreimal denselben Schlüssel, und JSON behält den letzten: Du bekommst {"name": "c"}, und zwei Datenspalten sind ohne jede Fehlermeldung weg. Dieser Konverter benennt stattdessen um: name, name_2, name_3. Er behandelt auch den Folgefall, in dem der erfundene Name mit einem echten kollidiert — name,name,name_2 ergibt name, name_2 und name_2_2, weil der Umbenenner gegen alles bereits Vergebene prüft und nicht nur gegen die ursprünglichen Spaltennamen.
Eine leere Kopfzelle bekommt einen Positionsnamen: name,,name, über a,b,c,d ergibt name, column2, name_2 und column4. Spaltennamen werden getrimmt, aus " name , age " wird also name und age. Und die Breite der Ausgabe ist die der breitesten Zeile in der Datei, nicht die der Kopfzeile: a,b,c über den zwei Zeilen 1,2 und 3,4,5,6 gibt jedem Objekt vier Schlüssel, mit leerem c in der kurzen Zeile und einem column4, das die 6 trägt, die die Kopfzeile nie vorgesehen hat. Nichts wird verworfen, und das ist bei einem Konverter richtig: Wer eine zu lange Zeile stillschweigend abschneidet, zerstört genau die Zeile, die man hätte ansehen müssen.
Fall 5 — die Kodierung, die das Werkzeug nicht heilen kann
Eine CSV-Datei besteht aus Bytes. Nichts darin sagt, welche Tabelle diese Bytes in Zeichen verwandelt, und RFC 4180 legt diese Information in einen MIME-Parameter, den eine Datei auf der Platte nicht trägt. Zwei Mechanismen schließen die Lücke teilweise. Eine Byte Order Mark am Dateianfang kennzeichnet UTF-8, UTF-16 LE und UTF-16 BE, und der Dateileser des Browsers verbraucht sie: Lege eine UTF-16-LE-Datei mit BOM in das Werkzeug, und der Text kommt korrekt dekodiert an, die Marke bereits entfernt. Das Werkzeug entfernt danach selbst noch einmal eine BOM, was den Fall abfängt, in dem die Marke über die Zwischenablage statt über eine Datei ankommt.
Offen bleibt die Lücke bei der Datei ganz ohne Marke, und das sind die meisten. Speichere eine Tabelle als einfaches CSV auf einem westeuropäischen Windows-Rechner, und du bekommst Windows-1252, ein Byte pro Zeichen, ohne BOM. Dieser Konverter hat keine Kodierungsauswahl: Der Leser fällt auf UTF-8 zurück, das Byte E9, das é bedeutete, ist kein gültiges UTF-8 und wird durch U+FFFD ersetzt. Das Werkzeug parst danach sauber und liefert {"name": "Andr�", "city": "K�ln"} ohne jede Warnung, denn aus seiner Sicht ist nichts schiefgegangen. U+FFFD bewahrt keine Spur des ersetzten Bytes, das ist also nachträglich nicht zu reparieren: Exportiere die Datei neu als UTF-8, oder füge den Text ein, statt die Datei abzulegen, denn Text in der Zwischenablage wurde von der besitzenden Anwendung bereits dekodiert.
Ein letzter Kodierungsfall hat eine scharfe Kante: UTF-16 ohne Byte Order Mark. Es gibt nichts zu schnüffeln, die Datei wird also als UTF-8 gelesen, jedes zweite Byte ist eine Null, und zurück kommt ein einziges Objekt, dessen Schlüssel NUL-Zeichen enthält. Das sieht nach Müll aus und nicht nach leicht falschem Text, und das ist der gute Ausgang: Du merkst es sofort. Gefährlich sind die stillen Fehlschläge, und Windows-1252 als UTF-8 gelesen ist der stillste von allen, weil die Spalten perfekt aufgehen und nur die Buchstaben mit Akzent falsch sind.
Der sechste Fall, den niemand aufzählt: die sep=-Zeile
Excel akzeptiert eine erste Zeile der Form sep=; als Anweisung, welches Zeichen die Felder trennt, und viele Exportroutinen schreiben sie, damit eine Semikolondatei bei einem Leser sauber aufgeht, dessen Listentrennzeichen das Komma ist. Sie steht nicht in RFC 4180 und stand nie darin: Es ist eine Herstellerkonvention, die sich verbreitet hat, weil sie funktioniert. Für einen Konverter, der nie von ihr gehört hat, ist sie schlicht der erste Datensatz der Datei.
Genau das passiert hier. Gib dem Konverter sep=; gefolgt von Name;Ville;Montant und zwei Datenzeilen: Die automatische Erkennung wählt korrekt das Semikolon — weil die sep=-Zeile selbst eines enthält — aber der Kopfzeilenschritt verbraucht sie. Du bekommst drei Objekte statt zwei, mit den Schlüsseln "sep=", column2 und column3, und die echten Spaltennamen Name, Ville und Montant erscheinen als Werte des ersten. Beim Blick auf die Ausgabe fällt es sofort auf und bleibt unsichtbar, wenn man sie direkt weiterleitet. Lösche die erste Zeile vor der Umwandlung, oder wandle zuerst das Trennzeichen um und lass den Trennzeichen-Konverter den Hinweis für dich neu schreiben.
| Eingabe | Was herauskommt | Warum |
|---|---|---|
| Tom,"Paris, France" | Zwei Felder: Tom und Paris, France | Der Parser führt einen Zitat-Zustand; ein Trennzeichen in Anführungszeichen ist Inhalt |
| Tom, "Paris, France" (Leerzeichen nach dem Komma) | Drei Felder: Tom, " Paris und France" | RFC 4180 Abschnitt 2.4: Das Leerzeichen gehört zum Feld, das Anführungszeichen öffnet also nichts |
| 0044 mit eingeschalteter Typumwandlung | Die Zeichenkette "0044" | Number("0044") druckt als 44, was nicht dem Angekommenen entspricht, die Zelle bleibt unangetastet |
| TRUE mit eingeschalteter Typumwandlung | Die Zeichenkette "TRUE"; nur kleingeschriebenes true wird zum Boolean | Der Test ist ein wörtlicher Vergleich mit den beiden JSON-Schlüsselwörtern, die kleingeschrieben sind |
| name,name,name über a,b,c | Schlüssel name, name_2 und name_3 — alle drei Werte bleiben | Ein wiederholter Schlüssel im Objekt zerstört Daten, also werden der zweite und dritte umbenannt |
| Eine Windows-1252-Datei, im Werkzeug abgelegt | Andr� und K�ln, sauber geparst, ohne Warnung | Keine Kodierungsauswahl: Der Leser nimmt UTF-8 an und ersetzt jedes ungültige Byte |
| Eine Datei, die mit sep=; beginnt | Das Semikolon wird richtig erkannt, aber sep= wird zum ersten Schlüssel und die echte Kopfzeile zur Datenzeile | Der Hinweis ist eine Excel-Konvention, in keiner CSV-Definition enthalten, der Parser liest ihn als Datensatz |
Häufige Fragen
- Typumwandlung einschalten oder auslassen?
- Lass sie aus, sofern nicht etwas weiter unten echte Zahlen braucht. Eine Zeichenkette ist eine verlustfreie Darstellung dessen, was in der Zelle stand; eine Zahl ist eine verlustbehaftete, und der Verlust ist irreversibel. Die Rundlaufsicherung sorgt dafür, dass genau dieses Werkzeug 0044, 1.0 oder eine 19-stellige Kennung nicht beschädigt, aber es wandelt eine Spalte von Postleitzahlen ohne führende Null um: 75001 und 75008 werden Zahlen, während ein niederländischer Code wie 1012 AB Zeichenkette bleibt — eine Spalte, zwei Typen, und wer das JSON verarbeitet, muss beides können. Wenn du Zahlen brauchst, wandle die betreffenden Spalten hinterher um, wo du sie benennen kannst, statt eine Heuristik spaltenweise entscheiden zu lassen.
- Woher weiß der Konverter, dass meine Datei Semikolons verwendet?
- Er zählt Kandidaten — Komma, Semikolon, Tab und Pipe — nur im ersten Datensatz, überspringt alles in Anführungszeichen und nimmt das häufigste. Nur den ersten Datensatz zu lesen ist Absicht: Eine Kopfzeile wie "Nom;Prénom" soll nicht von einem Komma bewertet werden, das dreihundert Zeilen weiter unten in einer zitierten Adresse steckt. Die Grenze ist das Spiegelbild davon. Enthält deine Kopfzeile ein Komma und benutzen die Datenzeilen Semikolons, wählt die Erkennung das Komma, und jede Zeile wird ein einziges Feld. Zwei Symptome verraten es sofort: ein einziger Schlüssel je Objekt und ein Schlüssel, dessen Name die ganze Kopfzeile ist. Im Zweifel setze das Trennzeichen ausdrücklich, statt dich auf die Erkennung zu verlassen.
- Warum wurden aus meinen Akzentbuchstaben Fragezeichen oder schwarze Rauten?
- Weil die Datei kein UTF-8 war und niemand das dem Leser gesagt hat. Die schwarze Raute mit Fragezeichen ist U+FFFD, das Unicode-Ersatzzeichen, und genau das gibt ein Dekodierer aus, wenn eine Bytefolge in der angenommenen Kodierung ungültig ist. Deine Datei war fast sicher Windows-1252 oder ISO 8859-1, wo é das einzelne Byte E9 ist; UTF-8 braucht für é zwei Bytes, und E9 allein ist der zulässige Anfang von gar nichts. Der Schaden entsteht, bevor der CSV-Parser läuft, keine CSV-Einstellung macht ihn rückgängig. Öffne das Original in einem Editor, der die Kodierung wählen lässt, speichere als UTF-8 und wandle erneut um. Kommt die Datei aus einer Tabellenkalkulation, exportiere sie mit der UTF-8-Option statt als einfaches CSV.
- Meine Zeilen haben nicht alle gleich viele Felder. Gehen Daten verloren?
- Nein. Die Ausgabebreite ist die der breitesten Zeile in der Datei, auch bei Zeilen, die breiter sind als die Kopfzeile. Eine kurze Zeile bekommt leere Zeichenketten für die fehlenden Spalten; eine lange Zeile bekommt zusätzliche Schlüssel namens column4, column5 und so weiter für Felder, die die Kopfzeile nie benannt hat. Nichts wird abgeschnitten, und das zählt: Eine zu lange Zeile ist meist das Symptom eines nicht maskierten Trennzeichens weiter oben, und Abschneiden würde die Spur verwischen. Siehst du column4 im JSON, obwohl die Kopfzeile nur drei Namen hatte, suche ein Feld mit einem nicht zitierten Trennzeichen — dort ist die Datei entgleist.
- Gibt es eine CSV-Variante ohne diese Probleme?
- Innerhalb von CSV nicht, denn das Format hat keinen Ort für die Metadaten, die die Fragen entscheiden würden. Was es gibt, sind darübergelegte Konventionen: eine begleitende Schemadatei, die Spalten und Typen benennt, ein festes, zwischen beiden Systemen vereinbartes Exportprofil, oder ein Format, das seine Typen selbst mitbringt. Kontrollierst du beide Enden, löst JSON Lines — ein JSON-Objekt pro Zeile — Zitierung, Zeilenumbrüche und Typen auf einen Schlag, um den Preis einer größeren Datei, die sich nicht in einer Tabellenkalkulation öffnet. Kontrollierst du nicht beide Enden, lautet die praktische Antwort: langweilig sein. UTF-8 mit BOM, durchgehend Komma oder Semikolon, jedes Feld zitiert, keine sep=-Zeile, und eine Kopfzeile mit eindeutigen Namen ohne das Trennzeichen.
Artikel, die dich interessieren könnten
Alle Ratgeber →Ähnliche Tools
Das hier beschreibt, was diese Konverter heute tun — geprüft, indem sie ausgeführt wurden — und nicht, was ein Standard einem Konverter vorschreibt. CSV hat keinen normativen Standard: RFC 4180 ist Informational und beschreibt gängige Praxis, weshalb zwei korrekt wirkende Werkzeuge bei derselben Datei auseinanderlaufen können, ohne dass eines falsch liegt. Abflachen, Typerkennung und Array-Erkennung sind Konventionen, keine Regeln. Bevor du Daten konvertierst, die du nicht neu exportieren kannst, lauf zuerst über eine Kopie und vergleiche Zeilen- und Spaltenzahl an beiden Enden.
Quellen
- IETF — RFC 4180, Common Format and MIME Type for Comma-Separated Values (CSV) Files, October 2005 — Informational, not a standard: section 2 rules 5 to 7 on double quotes, section 2.4 on spaces being part of a field, and the header and charset parameters of the text/csv media type
- IETF — RFC 8259, The JavaScript Object Notation (JSON) Data Interchange Format, December 2017 — section 4 on object member names being unordered and the consequences when names repeat, and section 6 on the interoperability limits of numbers
- WHATWG — Encoding Standard — the decoder algorithms, the BOM sniffing rules, and the use of U+FFFD as the replacement for a byte sequence that is not valid in the chosen encoding
- W3C — File API — the read operation and its encoding determination: an explicit encoding, then the blob's charset parameter, then a byte order mark, then UTF-8 as the fallback
Hast du einen Fehler in diesem Artikel entdeckt?