So konvertierst du YAML in JSON: Häufige Fallstricke, die du vermeiden solltest
Warum YAML und JSON nicht so austauschbar sind, wie sie aussehen
YAML und JSON sehen sich ähnlich und sind eng miteinander verwandt. YAML 1.2 ist sogar eine Obermenge von JSON, sodass jedes gültige JSON auch gültiges YAML ist. Klingt super, oder? Ist es auch, bis du eine echte YAML-Datei konvertierst und deine erste stille Datenkorruption entdeckst. Die beiden Formate haben einfach unterschiedliche Designziele. JSON wurde für Maschinen entwickelt: strikt, eindeutig und ohne Platz für Kommentare. YAML hingegen wurde für Menschen gemacht. Es verwendet Einrückungen für die Struktur, unterstützt mehrzeilige Strings, erlaubt Inline-Kommentare und verfügt über eine Typinferenz, die versucht, deine Absicht zu erraten. Genau dieses hilfreiche Raten ist der Punkt, an dem Konvertierungen schiefgehen. Ein YAML-Parser könnte den String 'yes' lesen und ihn als den booleschen Wert `true` interpretieren. Er könnte '1.0' sehen und eine Gleitkommazahl erzeugen, nicht den String, den du eingegeben hast. Das sind keine Bugs; die YAML-Spezifikation funktioniert wie vorgesehen. Das Problem entsteht, weil JSON keine solche Mehrdeutigkeit kennt. Sobald dein YAML-Wert in den geparsten Daten zu einem booleschen Wert wird, schreibt die JSON-Ausgabe `true`, und der ursprüngliche String ist für immer verloren. Wenn du Konfigurationsdateien für ein Kubernetes-Cluster, eine OpenAPI-Spezifikation oder eine CI/CD-Pipeline konvertierst, können diese stillen Typänderungen alles Nachgelagerte lahmlegen, ohne eine einzige Fehlermeldung. Um Dateien zuverlässig zu konvertieren, musst du diese fundamentalen Unterschiede verstehen.
Der schnellste Weg zur Konvertierung: CocoConvert verwenden
Wenn du einfach nur eine Datei konvertieren musst, ist der schnellste Weg, ein spezialisiertes Tool zu verwenden, anstatt ein Skript zusammenzuschustern. Der [YAML-zu-JSON-Konverter](/convert/yaml-to-json) von CocoConvert erledigt das gesamte Parsen und Serialisieren und liefert dir sofort eine korrekt formatierte, UTF-8-kodierte Ausgabe. Der Prozess ist denkbar einfach: Füge dein YAML ein, lade eine .yaml- oder .yml-Datei hoch und klicke auf „Konvertieren“. Dein JSON erscheint im Ausgabefenster und kann kopiert oder heruntergeladen werden. CocoConvert verwendet moderne YAML-1.2-Parsing-Regeln, sodass du nicht vom alten „Norwegen-Problem“ erwischt wirst, bei dem der String 'NO' als der boolesche Wert `false` fehlinterpretiert wurde. Wenn dein Quell-YAML einen Einrückungsfehler hat, erhältst du einen klaren Parse-Fehler mit Zeilennummer anstelle einer stillschweigend verstümmelten Ausgabe. Es verarbeitet auch YAML-Dateien mit mehreren Dokumenten (die mit `---`-Trennzeichen) korrekt. Diese werden in ein JSON-Array konvertiert, wobei jedes Dokument zu einem Array-Element wird. Das ist das standardmäßige, erwartete Verhalten, aber es ist gut, sich daran zu erinnern, falls du ein unerwartetes Array in deiner Ausgabe siehst, weil deine Datei mit `---` begann. Es gibt eine Einschränkung: Das Tool unterstützt keine YAML-Anker und -Aliase, die auf Knoten in verschiedenen Dokumenten derselben Datei verweisen. Für diese komplexen Fälle mit dokumentübergreifenden Ankern musst du sie zuerst auflösen, entweder von Hand oder mit einem lokalen Skript, bevor du die Datei zur Konvertierung hochlädst.
YAML-Typumwandlung: Die Fallstricke, die am härtesten zuschlagen
Typumwandlung (Type Coercion) ist die Hauptursache für Datenverlust bei der Konvertierung von YAML in JSON. Bevor du eine Produktionsdatei konvertierst, musst du sie unbedingt auf diese speziellen Fallstricke prüfen. **Boolesche Werte aus unerwarteten Strings.** Alte YAML-1.1-Parser (wie PyYAML vor Version 6.0) interpretierten `yes`, `no`, `on` und `off` als boolesche Werte. Modernes YAML 1.2 behandelt nur `true` und `false` auf diese Weise, aber wenn deine Quelldatei mit einem älteren Tool erstellt wurde, könnte sie 'yes' enthalten, obwohl eigentlich der String 'yes' gemeint ist. Wenn du den Ursprung der Datei nicht kennst, musst du manuell nach diesen Werten suchen. **Oktale Ganzzahlen.** Das ist ein Klassiker. In YAML wird ein Wert wie `0755` als die oktale Ganzzahl 493 geparst. Das ist eine berüchtigte Falle in Kubernetes-Manifesten zum Setzen von Dateiberechtigungen. Bei der Konvertierung wird dein JSON die Zahl `493` enthalten, nicht den String `'0755'`. Wenn ein nachgelagerter Prozess versucht, diese Zahl in einem `chmod`-Aufruf zu verwenden, sind die Berechtigungen komplett falsch, und du bekommst keinen Fehler. **Gleitkomma-Randfälle.** YAML versteht spezielle Gleitkommawerte wie `.inf`, `-.inf` und `.nan`. JSON nicht. CocoConvert löst das, indem es sie in die Strings 'Infinity', '-Infinity' und 'NaN' umwandelt. Das ist eine sinnvolle Ausweichlösung, aber wenn deine Anwendung nur Zahlen erwartet, könnte sie an diesen String-Werten scheitern, was eine Nachbearbeitung erfordert. **Null-Darstellungen.** YAML ist bei Nullwerten flexibel und akzeptiert `null`, `~` oder sogar nur einen leeren Wert nach einem Schlüssel. All diese werden in JSON zu einem standardmäßigen `null`. Das ist normalerweise in Ordnung, aber denk daran, dass ein Schlüssel, nach dessen Doppelpunkt nichts steht, zu einem JSON-`null` und nicht zu einem leeren String `""` wird.
Umgang mit mehrzeiligen Strings und Kommentaren
YAML bietet zwei leistungsstarke Syntaxen für mehrzeilige Strings, die keine direkte Entsprechung in JSON haben: literale Block-Skalare (`|`) und gefaltete Block-Skalare (`>`). Ein literaler Block (`|`) behält jeden einzelnen Zeilenumbruch bei. Ein gefalteter Block (`>`) wandelt einfache Zeilenumbrüche in Leerzeichen um, behält aber doppelte Zeilenumbrüche als tatsächliche Zeilenumbrüche bei. Beide Syntaxen erzeugen einen einzigen JSON-String, aber die subtilen Unterschiede bei der Behandlung von Zeilenumbrüchen sind entscheidend für eingebettete Inhalte wie Shell-Skripte, SQL-Abfragen oder Zertifikate. Zum Beispiel wird dieses YAML: ```yaml script: | echo hello echo world ``` zu diesem JSON: ```json {"script": "echo hello\necho world\n"} ``` Beachte, dass der abschließende Zeilenumbruch (`\n`) beim literalen `|`-Stil standardmäßig erhalten bleibt. Um ihn zu entfernen, würdest du den Chomping-Indikator `|-` verwenden. Jeder, der schon mal ein CI-Skript debuggen musste, das an einem subtilen Leerzeichenunterschied scheiterte, kennt diesen Schmerz. Wenn man das falsch macht, können Skripte oder APIs, die empfindlich auf Leerzeichen reagieren, kaputtgehen. Kommentare sind ein viel schwierigeres Problem. YAML unterstützt Kommentare mit `#`. JSON nicht. Punkt. Das bedeutet, dass bei der Konvertierung jeder einzelne Kommentar in deiner YAML-Datei dauerhaft gelöscht wird. Der gesamte entscheidende Kontext, der erklärt, *warum* ein bestimmter Wert gesetzt ist – eine gängige Praxis bei Infrastructure-as-Code – verschwindet aus der JSON-Ausgabe. Innerhalb der JSON-Spezifikation gibt es dafür keine Lösung. Meine Empfehlung ist einfach: Behandle dein kommentiertes YAML immer als die Quelle der Wahrheit und das generierte JSON als ein wegwerfbares Build-Artefakt. Manche Teams verwenden JSONC (JSON mit Kommentaren), aber das verschiebt das Kompatibilitätsproblem nur weiter nach hinten.
Anker, Aliase und Merge Keys
YAMLs Anker und Aliase sind eine fantastische Funktion, um deine Dateien DRY (Don't Repeat Yourself) zu halten, aber sie bringen Komplexität in die JSON-Konvertierung. Du definierst einen Anker mit `&anchor-name` und referenzierst ihn dann mit `*anchor-name`. Ein YAML-Parser expandiert diese Aliase beim Lesen der Datei und baut die endgültige Datenstruktur im Speicher auf. Die JSON-Ausgabe enthält daher den vollständig expandierten, duplizierten Inhalt, ohne eine Spur der ursprünglichen Anker. Betrachte dieses gängige Muster: ```yaml defaults: &defaults timeout: 30 retries: 3 production: <<: *defaults host: prod.example.com staging: <<: *defaults host: staging.example.com ``` Die `<<`-Syntax ist ein YAML Merge Key. Das resultierende JSON wird sein: ```json { "defaults": {"timeout": 30, "retries": 3}, "production": {"timeout": 30, "retries": 3, "host": "prod.example.com"}, "staging": {"timeout": 30, "retries": 3, "host": "staging.example.com"} } ``` Die Expansion ist korrekt, aber die Prägnanz des ursprünglichen YAMLs ist verloren gegangen. Wenn 50 Dienste von diesem Defaults-Anker erben, wird das JSON 50 Kopien dieser Daten enthalten. Für eine Maschine ist das völlig in Ordnung. Für einen Menschen, der versucht, die Datei zu lesen, oder für Systeme, bei denen die Dateigröße eine Rolle spielt, ist es ein erheblicher Nachteil. Beachte, dass die Unterstützung für Merge Keys (`<<`) technisch gesehen eine YAML-Erweiterung ist und nicht Teil der Kernspezifikation, sodass einige strikte Parser sie ablehnen werden. CocoConvert verarbeitet Merge Keys ohne Probleme. Wenn du eine Konvertierung mit Pythons PyYAML skriptest, musst du `yaml.full_load()` oder `yaml.safe_load()` verwenden. Vermeide das alte `yaml.load()` ohne ein `Loader`-Argument, da es seit PyYAML 5.1 aufgrund erheblicher Sicherheitsrisiken veraltet ist.
YAML programmatisch in JSON konvertieren
Für Massenkonvertierungen, Integrationen in Build-Pipelines oder jede Art von automatisierter Verarbeitung benötigst du eine Kommandozeilen- oder skriptbasierte Lösung. Ein Web-Tool ist super für einzelne Aktionen, aber Automatisierung erfordert Code. Dies sind die zuverlässigsten Wege, dies zu tun. **Python (die portabelste Option):** ```python import yaml, json, sys with open(sys.argv[1], 'r') as f: data = yaml.safe_load(f) print(json.dumps(data, indent=2, ensure_ascii=False)) ``` Verwende immer `yaml.safe_load()`. Das alte `yaml.load()` ist ein Sicherheitsalbtraum, der beliebigen Code aus einer bösartigen YAML-Datei ausführen kann. Das Argument `ensure_ascii=False` ist ebenfalls eine gute Angewohnheit, da es Unicode-Zeichen beibehält, anstatt sie zu escapen. **Node.js:** ```javascript const yaml = require('js-yaml'); const fs = require('fs'); const data = yaml.load(fs.readFileSync(process.argv[2], 'utf8')); console.log(JSON.stringify(data, null, 2)); ``` Die `js-yaml`-Bibliothek verwendet standardmäßig moderne YAML-1.2-Regeln (seit v4.0). Wenn du in einem älteren Projekt arbeitest, überprüfe deine `package.json`. Versionen vor 4.0 verwenden YAML-1.1-Regeln und werden Strings wie 'yes' und 'no' fälschlicherweise in boolesche Werte umwandeln. **yq (Kommandozeilen-Tool):** ```bash yq -o=json eval '.' input.yaml > output.json ``` Ehrlich gesagt ist `yq` das beste Tool für diese Aufgabe auf der Kommandozeile. Es ist ein speziell entwickelter YAML-Prozessor, der alles korrekt handhabt – Dateien mit mehreren Dokumenten, Anker, Merge Keys – mit einem einfachen Flag für die JSON-Ausgabe. Installiere es mit Homebrew auf macOS (`brew install yq`) oder hol dir die Binärdatei von GitHub für Linux/Windows. Für eine schnelle Konvertierung, ohne etwas installieren zu müssen, ist das [CocoConvert YAML-zu-JSON-Tool](/convert/yaml-to-json) natürlich immer noch der schnellste Weg.
Validiere deine Ausgabe, bevor du sie verwendest
Eine Datei zu konvertieren, ohne sie zu validieren, ist ein Rezept, um subtile Fehler in die Produktion einzuschleusen. Eine JSON-Datei kann syntaktisch vollkommen gültig sein, aber semantisch falsche Daten enthalten, wie die Typumwandlungen, die wir besprochen haben. Hier ist eine praktische Checkliste, die dich vor zukünftigem Kopfzerbrechen bewahrt. **Syntax-Validierung.** Lass die Ausgabe mindestens durch einen JSON-Linter laufen. Dein Code-Editor (wie VS Code oder eine JetBrains IDE) macht das wahrscheinlich automatisch. Auf der Kommandozeile ist Pythons eingebautes `json.tool` ein zuverlässiges Arbeitstier: `python3 -m json.tool output.json > /dev/null`. Es beendet sich mit dem Code 0 bei gültigem JSON und sagt dir im Fehlerfall genau, wo es kaputtgegangen ist. **Schema-Validierung.** Verwende für kritische Dateien ein Schema. Wenn dein Zielformat ein JSON-Schema hat (üblich für OpenAPI-Spezifikationen, AWS CloudFormation und Kubernetes CRDs), validiere dagegen. Ein Tool wie `ajv-cli` (`ajv validate -s schema.json -d output.json`) wird Typ-Inkonsistenzen aufdecken, die eine einfache Syntaxprüfung nicht sehen kann. **Vergleich (Diff) mit einer bekanntermaßen funktionierenden Version.** Wenn du eine Referenz-JSON-Datei hast, ist ein Diff unerlässlich. Aber normalisiere zuerst die Reihenfolge der Schlüssel, um laute, bedeutungslose Unterschiede zu vermeiden. Das `jq`-Tool kann Schlüssel deterministisch sortieren: `jq --sort-keys . output.json > normalized.json`. Denk daran, die Reihenfolge der Schlüssel in JSON spielt keine Rolle, aber sie wird dich in den Wahnsinn treiben, wenn du versuchst, Dateien zu vergleichen. **Stichprobenartige Prüfung auf umgewandelte Typen.** Wenn du vermutest, dass dein YAML Werte wie '1.0' oder '0755' enthielt, überprüfe die JSON-Ausgabe direkt. Ein schnelles `grep -n "0755" output.json` verrät dir sofort, ob dein oktaler String die Konvertierung überlebt hat oder in eine nutzlose Ganzzahl umgewandelt wurde. Ernsthaft, sich fünf Minuten Zeit zu nehmen, um deine Ausgabe vor einem Commit oder Deployment zu validieren, ist immer schneller, als einen Produktionsvorfall zu debuggen, der durch einen booleschen Wert verursacht wurde, der eigentlich ein String sein sollte.