YAML vs JSON: Der ehrliche Vergleich mit eigenen Messungen (2026)

YAML vs JSON: Der ehrliche Vergleich mit eigenen Messungen (2026)

YAML vs JSON ist eine der Fragen, die fast jeder stellt, der zum ersten Mal eine docker-compose.yaml, eine GitHub-Actions-Datei oder eine Kubernetes-Konfiguration öffnet. Beide Formate speichern strukturierte Daten als Text, beide kennen Objekte, Listen, Zahlen und Wahrheitswerte. Und trotzdem verhalten sie sich in der Praxis völlig unterschiedlich.

Die kurze Antwort: JSON ist ein strenges, kleines Datenformat, das Programme untereinander austauschen. YAML ist ein großes, nachsichtiges Format, das Menschen von Hand schreiben sollen. JSON ist schneller, eindeutiger und sicherer. YAML ist lesbarer, erlaubt Kommentare und spart Klammern. Der Preis für diese Bequemlichkeit ist, dass YAML Dinge errät, und manchmal falsch.

Damit dieser Artikel nicht nur Lehrbuchwissen wiederholt, haben wir am 14. Oktober 2026 auf unserem eigenen Server drei YAML-Parser gegen JSON antreten lassen: PyYAML 6.0.3 (Python), js-yaml 4.3.2 und yaml 2.9.1 (beide Node.js 22). Drei Ergebnisse vorweg:

1. Dieselben 50.000 Datensätze las JSON.parse in 30 ms. js-yaml brauchte 308 ms, die Bibliothek yaml 4,2 Sekunden und PyYAML in reinem Python 20 Sekunden.

2. PyYAML las den Ländercode NO als false, die Uhrzeit 22:22 als die Zahl 1342 und die Postleitzahl 01067 als 567. Ohne Warnung.

3. Eine 254 Byte kleine YAML-Datei wurde nach dem Einlesen zu 22,9 MB JSON. Nur eine der drei Bibliotheken hat das abgelehnt.

Zwei leuchtende Strukturen nebeneinander: links ein Baum aus eingerückten Lichtbalken, rechts verschachtelte Klammerformen mit kleinen leuchtenden Würfeln

YAML vs JSON: Der grundlegende Unterschied

Wenn du noch nicht genau weißt, wie eine JSON-Datei aufgebaut ist, lies zuerst unseren Grundlagenartikel Was ist eine JSON-Datei?. Hier geht es um den direkten Vergleich.

So sieht JSON aus

JSON (JavaScript Object Notation) wurde Anfang der 2000er von Douglas Crockford bekannt gemacht und ist heute als RFC 8259 standardisiert. Die gesamte Grammatik passt auf eine Postkarte: Objekte in geschweiften Klammern, Listen in eckigen Klammern, Texte in doppelten Anführungszeichen, dazu Zahlen, true, false und null. Das war es.

{
  "server": {
    "host": "example.com",
    "port": 8080,
    "debug": false
  },
  "laender": ["DE", "AT", "NO"]
}

So sieht YAML aus

YAML (rekursiv für „YAML Ain’t Markup Language“) erschien 2001. Die aktuelle Fassung ist YAML 1.2, deren letzte Überarbeitung 1.2.2 aus dem Jahr 2021 stammt. YAML verzichtet auf Klammern und Anführungszeichen, die Struktur entsteht über Einrückung:

# Konfiguration für den Webserver
server:
  host: example.com
  port: 8080
  debug: false
laender:
  - DE
  - AT
  - "NO"   # Anführungszeichen nötig, warum: siehe unten

Das Beispiel zeigt schon die wichtigste Eigenschaft: YAML liest sich fast wie eine Notiz. Und es zeigt die wichtigste Falle, denn in der letzten Zeile stehen Anführungszeichen, die man ohne Vorwissen weglassen würde.

YAML ist (fast) eine Obermenge von JSON

Seit YAML 1.2 ist jede gültige JSON-Datei auch eine gültige YAML-Datei. Du kannst also eine .json-Datei mit einem YAML-Parser lesen. Wir haben das getestet: js-yaml las unsere 5,8 MB große JSON-Testdatei problemlos, sogar schneller als die gleichen Daten im YAML-Stil (205 statt 308 ms). Umgekehrt gilt das nicht: Ein JSON-Parser lehnt fast jede YAML-Datei ab.

Kleine Einschränkung: Das gilt sauber nur für YAML-1.2-Parser. Ältere Parser nach YAML 1.1, darunter das weit verbreitete PyYAML, stolpern an Randfällen. Dazu gleich mehr.

Die Unterschiede in einer Tabelle

JSONYAML
Gedacht fürDatenaustausch zwischen ProgrammenKonfiguration, von Menschen geschrieben
Struktur überKlammern {} und []Einrückung (nur Leerzeichen)
Kommentareneinja, mit #
AnführungszeichenPflicht für Texte und Schlüsselmeist optional
Mehrzeilige Textenur mit \nja, mit | und >
WiederverwendungneinAnker & und Aliase *
Mehrere Dokumente pro Dateinein (außer NDJSON)ja, getrennt mit ---
Datentypen6, festerraten aus dem Wert, je nach Version
Spezifikationwenige Seitenüber 80 Seiten
Parse-Geschwindigkeit (unser Test)30 ms308 ms bis 20 s
Doppelte Schlüsselmeist still: letzter gewinntje nach Parser Fehler oder still
Typische Dateienpackage.json, API-Antworten, tsconfig.jsondocker-compose.yaml, GitHub Actions, Kubernetes, Ansible

Unser Testaufbau

Alle Messungen liefen am 14. Oktober 2026 auf unserem Produktionsserver (Hetzner, Ubuntu, Node.js 22.23, Python 3). Getestet haben wir drei YAML-Bibliotheken, die du mit großer Wahrscheinlichkeit irgendwo im Einsatz hast, ohne es zu wissen:

  • PyYAML 6.0.3: der Standard in Python, versteht YAML 1.1. Steckt in Ansible, in vielen CI-Werkzeugen und unzähligen Skripten.
  • js-yaml 4.3.2: der Standard im Node-Ökosystem, versteht YAML 1.2. Mit wöchentlich zig Millionen Downloads eine der meistgenutzten Bibliotheken überhaupt.
  • yaml 2.9.1 (von Eemeli Aro): die modernere Node-Bibliothek, Standard YAML 1.2, auf Wunsch auch 1.1.

Für die Geschwindigkeitstests haben wir 50.000 Produkt-Datensätze mit festem Zufalls-Startwert erzeugt (ID, Name, Preis, aktiv, zwei Tags, Lagerort, Menge) und jeden Lauf fünfmal gemessen. In der Tabelle steht jeweils der Median.

Test 1: Wie schnell ist YAML im Vergleich zu JSON?

Zwei Bahnen aus Licht: eine kurze gerade, die sofort am Ziel ist, und eine lange gewundene Spirale

Zuerst die Dateigrößen derselben Daten:

DateiGrößegzip -9
JSON kompakt5,79 MB682 KB
JSON eingerückt (2 Leerzeichen)11,29 MB–
YAML (js-yaml-Ausgabe)7,29 MB707 KB

YAML ist hier rund 26 Prozent größer als kompaktes JSON, aber 35 Prozent kleiner als eingerücktes JSON. Komprimiert liegen beide praktisch gleichauf. Die Dateigröße ist also selten ein echtes Argument.

Ganz anders beim Einlesen:

VorgangMedianFaktor zu JSON
JSON.parse (Node)30 ms1×
js-yaml load308 ms~10×
js-yaml load auf der JSON-Datei205 ms~7×
yaml 2.9 parse4.162 ms~140×
Python json.loads92 ms–
PyYAML CSafeLoader (C-Beschleunigung)7.776 ms~85× zu Python-JSON
PyYAML safe_load (reines Python)20.388 ms~220× zu Python-JSON

Und beim Schreiben:

VorgangMedian
JSON.stringify18 ms
yaml 2.9 stringify1.704 ms
js-yaml dump3.680 ms

Was das bedeutet: Für eine Konfigurationsdatei mit 50 Zeilen ist das völlig egal, da reden wir über Mikrosekunden. Sobald YAML aber als Austauschformat für echte Datenmengen benutzt wird, etwa für Exporte, Caches oder API-Antworten, wird es zur Bremse. Der Node-Prozess brauchte während der Testreihe zwischenzeitlich über 2 GB Arbeitsspeicher, überwiegend durch die YAML-Bibliotheken, die für jeden Knoten deutlich mehr Verwaltungsdaten anlegen als JSON.parse.

Bemerkenswert ist der Unterschied zwischen den beiden Node-Bibliotheken: yaml 2.9 ist beim Lesen über zehnmal langsamer als js-yaml. Das liegt daran, dass yaml intern einen vollständigen Syntaxbaum mit Kommentaren und Positionen aufbaut, damit man Dateien bearbeiten und wieder schreiben kann, ohne Kommentare zu verlieren. Das ist ein echtes Feature, kostet aber Zeit.

Und bei PyYAML lohnt ein Blick in die eigene Installation: Wenn yaml.CSafeLoader verfügbar ist, ist er bei uns 2,6-mal schneller als der Standard-safe_load. Viele Projekte nutzen ihn trotzdem nicht, weil safe_load der Name ist, der in jedem Tutorial steht.

Test 2: Das Norwegen-Problem und andere Typ-Überraschungen

Ein einzelner leuchtender Kippschalter, halb hell, halb rot, schwebend im dunklen Raum

Der wichtigste Unterschied zwischen YAML und JSON ist nicht die Syntax, sondern wer den Datentyp bestimmt. In JSON steht der Typ fest: "NO" ist ein Text, false ist ein Wahrheitswert, fertig. In YAML errät der Parser den Typ anhand des Werts. Und die Regeln dafür haben sich zwischen YAML 1.1 und 1.2 geändert.

Wir haben dieselbe kleine Datei an alle drei Parser gegeben:

laender: [DE, AT, NO, SE]
aktiv: yes
schalter: on
rechte: 0755
alt_oktal: 010
uhrzeit: 22:22
version: 1.10
plz: 01067
datum: 2026-10-14
hex: 0x1F

Das Ergebnis, umgerechnet in JSON:

ZeilePyYAML 6.0.3 (YAML 1.1)js-yaml 4.3.2 (1.2)yaml 2.9.1 (1.2)
NOfalse"NO""NO"
yestrue"yes""yes"
ontrue"on""on"
0755493 (oktal)755755
01081010
22:221342 (Sexagesimal)"22:22""22:22"
1.101.11.11.1
01067567 (oktal!)10671067
2026-10-14DatumDatum (als Zeitstempel)"2026-10-14"
0x1F313131

Das ist das sogenannte Norway-Problem: Ein Ländercode-Verzeichnis, in dem Norwegen plötzlich als false gespeichert wird. Es ist nicht ausgedacht, es ist ein Klassiker aus echten Fehlerberichten.

Ein paar Zeilen verdienen eine Erklärung:

  • 22:22 wird zu 1342. YAML 1.1 kennt Zahlen zur Basis 60, gedacht für Zeitangaben. 22 × 60 + 22 = 1342. Wer in einer Konfiguration eine Uhrzeit oder einen Port-Bereich wie 22:22 notiert, bekommt mit PyYAML eine Zahl.
  • 01067 wird zu 567. Das ist die Postleitzahl von Dresden. YAML 1.1 liest führende Nullen als Oktalzahl. Aber auch die 1.2-Parser liefern 1067, denn auch dort ist es eine Zahl, nur eben dezimal. Die führende Null ist in allen drei Fällen weg.
  • 1.10 wird zu 1.1. Bei allen drei Parsern. Wer Versionsnummern ohne Anführungszeichen schreibt, bekommt Version 1.1 statt 1.10. Das betrifft Python-Versionen in CI-Dateien besonders oft: python-version: 3.10 wird zu 3.1.
  • Das Datum ist bei js-yaml ein Zeitstempel um Mitternacht UTC, bei yaml 2.9 ein Text. Dieselbe Datei, dieselbe YAML-Version, unterschiedliche Typen.

Die Lehre: In YAML gehören alle Texte, die wie etwas anderes aussehen könnten, in Anführungszeichen. Ländercodes, Postleitzahlen, Versionsnummern, Uhrzeiten, Telefonnummern, Ja/Nein-Werte, die eigentlich Text sein sollen. In JSON stellt sich diese Frage gar nicht.

Die GitHub-Actions-Falle mit on:

Ein besonders schönes Beispiel liefern GitHub-Actions-Dateien. Jeder Workflow beginnt mit:

on:
  push:
    branches: [main]

PyYAML liest daraus den Schlüssel True, nicht "on". Wir haben es gemessen: {True: {'push': {'branches': ['main']}}}. GitHub selbst nutzt einen YAML-1.2-Parser, deshalb funktioniert der Workflow. Aber wer die Datei mit einem Python-Skript prüft oder umbaut, sucht vergeblich nach dem Schlüssel on.

Und Docker Compose?

Docker Compose ist hier gutmütig. Wir haben eine Datei mit DEBUG: no und LAND: NO geprüft. docker compose config (Docker 29.2.1, Compose v5.0.2) gab beide Werte als Text "no" und "NO" aus. Compose nutzt einen 1.2-orientierten Parser. Mehr zu den echten Fallen in Compose-Dateien steht in unserem Docker Compose Beispiel.

Test 3: Doppelte Schlüssel

Was passiert, wenn derselbe Schlüssel zweimal vorkommt? In langen Konfigurationsdateien passiert das schneller, als man denkt, zum Beispiel nach einem Copy-and-paste.

name: a
name: b
ParserErgebnis
PyYAML{'name': 'b'}, still
js-yamlFehler: duplicated mapping key (2:1)
yaml 2.9Fehler: Map keys must be unique at line 2, column 1
JSON.parse (Node){ name: 'b' }, still
Python json{'name': 'b'}, still
jq{"name": "b"}, still

Hier ist YAML ausnahmsweise strenger. Die YAML-Spezifikation verbietet doppelte Schlüssel ausdrücklich, und zwei der drei Parser halten sich daran. Der JSON-Standard sagt nur, Schlüssel „sollten“ eindeutig sein, und alle getesteten JSON-Parser nehmen kommentarlos den letzten Wert. PyYAML verhält sich wie ein JSON-Parser und verstößt damit gegen die eigene Spezifikation.

Test 4: Einrückung, Tabs und das fehlende Komma

YAML nutzt Einrückung als Syntax. Daraus folgen drei Fehlerarten, die es in JSON nicht gibt:

Tabs sind verboten. Eine Datei mit Tab-Einrückung bricht ab: found character '\t' that cannot start any token. Das ist gut, denn so fällt der Fehler auf. Unangenehm ist nur, dass man Tabs im Editor oft nicht sieht.

Ein Leerzeichen zu viel bricht ab. Drei statt zwei Leerzeichen vor host: lieferte einen Fehler in Zeile 3, Spalte 8. Auch das fällt auf.

Ein Leerzeichen zu wenig bricht nicht ab. Das ist die gefährliche Variante:

server:
  port: 80
host: x

Hier wurde host versehentlich nicht eingerückt. PyYAML liest daraus ohne jede Meldung {'server': {'port': 80}, 'host': 'x'}. Die Einstellung landet eine Ebene zu hoch, die Anwendung findet server.host nicht und nimmt den Standardwert. Kein Fehler, nur falsches Verhalten. In JSON wäre die gleiche Verschiebung nur mit einer verschobenen Klammer möglich, und die fällt beim Lesen sofort auf.

Umgekehrt zeigt sich JSONs Strenge beim Komma am Ende: {"a":1,} lehnen beide JSON-Parser ab. Python sagt Expecting property name enclosed in double quotes: line 1 column 8, Node sagt Expected double-quoted property name in JSON at position 7. PyYAML liest dieselbe Zeile klaglos als {'a': 1}. Wer ein Format sucht, das kleine Schlampereien verzeiht, ist bei YAML richtig. Wer eines sucht, das sie meldet, bei JSON.

Test 5: Die 254-Byte-Bombe (Anker und Aliase)

Ein kleiner leuchtender Samen, der in eine riesige fraktale Explosion aus verzweigten Lichtfäden aufbricht

YAML hat ein Feature, das JSON fehlt: Anker und Aliase. Mit &name markierst du einen Block, mit *name verwendest du ihn wieder. Das ist praktisch, um Wiederholungen zu vermeiden, etwa gemeinsame Einstellungen für mehrere Dienste:

standard: &standard
  restart: unless-stopped
  logging: { driver: json-file }

web:
  <<: *standard
  image: nginx

Dasselbe Feature lässt sich missbrauchen. Man verweist in jeder Ebene neunmal auf die vorherige Ebene, und nach sieben Ebenen stehen 9^7 = 4.782.969 Einträge im Speicher. Das ist die YAML-Version des „Billion Laughs“-Angriffs, den man aus XML kennt. Unsere Datei war genau 254 Bytes groß:

a: &a ["x","x","x","x","x","x","x","x","x"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
ParserEinlesenDanach als JSON ausgegeben
js-yamlok nach 2 ms22.868.593 Zeichen (22,9 MB) in 116 ms
PyYAML safe_loadok nach 1 ms28,2 MB in 0,2 s
yaml 2.9abgelehnt nach 9 ms: Excessive alias count indicates a resource exhaustion attack–

Interessant ist, warum das Einlesen so schnell ging: Die Parser legen Aliase als Verweise an, nicht als Kopien. Im Speicher ist die Datei zunächst klein. Die Explosion passiert erst, wenn jemand die Daten durchläuft, serialisiert, validiert oder in eine Datenbank schreibt. Mit einer Ebene mehr wären es 43 Millionen Einträge gewesen, mit zwei Ebenen mehr 387 Millionen, und dann ist der Server weg.

JSON kennt keine Verweise. Eine 254 Byte große JSON-Datei ist nach dem Einlesen ungefähr 254 Byte groß.

Test 6: Wenn YAML Code ausführt

Der zweite Sicherheitsunterschied ist schwerwiegender. YAML kennt Tags, mit denen man einen Wert als bestimmten Typ markieren kann. PyYAML unterstützt Python-spezifische Tags, mit denen sich beim Einlesen beliebige Funktionen aufrufen lassen. Unsere Testdatei:

x: !!python/object/apply:os.system ["echo PWNED > /tmp/gmyj/pwned.txt"]
Lade-FunktionErgebnis
yaml.safe_loadabgelehnt: ConstructorError: could not determine a constructor for the tag ...os.system
yaml.load(..., Loader=FullLoader)abgelehnt
yaml.unsafe_loadausgeführt. Die Datei pwned.txt mit dem Inhalt PWNED lag danach auf dem Server.

Mit unsafe_load (oder in alten PyYAML-Versionen vor 5.1 mit einfachem yaml.load ohne Loader) wird eine YAML-Datei aus fremder Quelle zur Fernsteuerung deines Servers. Genau das war über Jahre eine der häufigsten Sicherheitslücken in Python-Projekten. In Ruby gab es mit YAML.load dasselbe Problem.

Bei JSON gibt es dieses Problem nicht, weil das Format keine Typ-Tags kennt. json.loads und JSON.parse können nur die sechs Grundtypen erzeugen.

Regel für die Praxis: YAML aus fremden Quellen nur mit safe_load (Python) bzw. dem Standard-load von js-yaml 4 einlesen, das seit Version 4 sicher ist. Und für alles, was über eine API von außen kommt, lieber gleich JSON verwenden.

Kommentare, mehrzeilige Texte und Lesbarkeit: Wo YAML gewinnt

Nach so vielen Fallen muss man fair sein: YAML hat echte Vorteile, und sie sind der Grund, warum es überall in der Konfiguration steckt.

Kommentare. Das ist der wichtigste Punkt. In einer Konfigurationsdatei willst du erklären können, warum ein Wert so ist, wie er ist. JSON erlaubt keine Kommentare, und das war eine bewusste Entscheidung von Douglas Crockford. Die Folge sind Hilfsfelder wie "_comment": "..." oder Varianten wie JSONC, die viele Werkzeuge nicht verstehen.

Mehrzeilige Texte. Ein Shell-Skript in einer CI-Datei, ein Zertifikat, eine SQL-Abfrage: In YAML schreibst du das einfach als Block.

script: |
  npm ci
  npm run build
  rsync -a dist/ /var/www/

In JSON wäre das ein einziger Text mit \n dazwischen, den kein Mensch gerne liest oder bearbeitet.

Weniger Rauschen. Unsere 50.000 Datensätze bestanden in eingerücktem JSON zu einem großen Teil aus Anführungszeichen, Klammern und Kommas. Für Maschinen ist das egal, für Menschen, die eine Datei überfliegen, macht es einen spürbaren Unterschied.

Wiederverwendung. Anker und Aliase sind, trotz Bombe, für Konfigurationen mit vielen ähnlichen Blöcken sehr praktisch. Docker Compose, GitLab CI und viele andere Werkzeuge nutzen sie, um Wiederholungen zu sparen.

Mehrere Dokumente in einer Datei. Kubernetes-Manifeste bündeln oft Deployment, Service und Ingress in einer Datei, getrennt durch ---. In JSON bräuchte man dafür ein umschließendes Array oder mehrere Dateien.

Ein kompakter deutscher Einstieg in die YAML-Syntax (Coding Crashkurse). Das Video ist älter, die Grundlagen sind aber unverändert. Die Typ-Fallen aus diesem Artikel kommen darin nicht vor.

Wo JSON gewinnt

Eindeutigkeit. Eine JSON-Datei bedeutet in jedem Parser dasselbe. Unsere Typ-Tabelle oben hatte für YAML drei verschiedene Ergebnisse bei derselben Datei. Für JSON hätte sie eine einzige Spalte.

Geschwindigkeit. 10- bis 220-mal schnelleres Einlesen ist kein Detail, wenn Daten in großer Menge fließen.

Sicherheit. Keine Verweise, keine Typ-Tags, keine Code-Ausführung. Das Schlimmste, was eine bösartige JSON-Datei tun kann, ist groß zu sein.

Werkzeuge. Jede Programmiersprache bringt einen JSON-Parser in der Standardbibliothek mit. Browser können es nativ. Mit jq hast du auf der Kommandozeile ein mächtiges Werkzeug. Mit JSON Schema gibt es einen ausgereiften Standard, um Dateien zu prüfen. Für YAML brauchst du fast immer eine externe Bibliothek, und welche das ist, entscheidet über das Verhalten.

Fehler fallen auf. Ein fehlendes oder überzähliges Komma, eine fehlende Klammer, ein einfaches Anführungszeichen: JSON bricht ab und nennt die Stelle. YAML rät oft weiter.

Genau deshalb sind fast alle Web-APIs JSON-basiert. Wie Schnittstellen grundsätzlich funktionieren, erklärt unser Artikel Was ist eine API?, und warum auch GraphQL am Ende JSON zurückgibt, steht in REST vs GraphQL.

Wer nutzt was? Ein Blick in die Praxis

Die Arbeitsteilung in der Praxis ist erstaunlich klar. Wir haben in unserem eigenen Arbeitsverzeichnis gezählt (ohne node_modules und .git):

FormatAnzahl Dateien
.json12.528
.yaml und .yml379
.toml5

JSON überwiegt mit einem Faktor von über 30. Die JSON-Dateien sind dabei überwiegend Daten, die Programme geschrieben haben: Paketinformationen, Zwischenstände, Exporte, Zustandsdateien. Die YAML-Dateien sind fast ausschließlich von Hand geschriebene Konfiguration: Compose-Stacks, CI-Workflows, Übersetzungsdateien.

So sieht es auch in der Software-Welt allgemein aus:

  • YAML: Docker Compose, Kubernetes, Helm, GitHub Actions, GitLab CI, Ansible, Home Assistant, OpenAPI-Spezifikationen (oft), Frontmatter in Markdown-Dateien (auch dieser Artikel beginnt mit YAML).
  • JSON: REST-APIs, package.json, tsconfig.json, composer.json, Browser-Speicher, Logdateien im NDJSON-Format, Datenbank-Felder vom Typ JSON/JSONB, Konfigurationen von VS Code.
  • TOML: Rust (Cargo.toml), Python-Projekte (pyproject.toml), Hugo. TOML ist der dritte Weg: Kommentare wie YAML, aber deutlich weniger Raterei bei den Typen.

Die Faustregel, die sich daraus ergibt: Schreibt ein Mensch die Datei und liest ein Programm sie, ist YAML (oder TOML) bequem. Schreibt ein Programm die Datei und liest ein Programm sie, ist JSON die bessere Wahl.

YAML in JSON umwandeln und umgekehrt

Weil YAML 1.2 eine Obermenge von JSON ist, ist die Umwandlung von JSON nach YAML immer verlustfrei. Umgekehrt gehen Kommentare, Anker und mehrere Dokumente verloren, und die Typen sind die, die der Parser erraten hat.

Auf der Kommandozeile:

# YAML → JSON mit Python (PyYAML, Achtung: YAML 1.1-Typen!)
python3 -c 'import sys,yaml,json; print(json.dumps(yaml.safe_load(sys.stdin), indent=2, default=str))' < config.yaml

# YAML → JSON mit Node (js-yaml, YAML 1.2)
npx js-yaml config.yaml > config.json

# JSON → YAML mit yq (Go-Version von Mike Farah)
yq -p json -o yaml '.' config.json > config.yaml

Ein Tipp aus unseren Tests: Wandle eine YAML-Datei einmal nach JSON um, bevor du ihr vertraust. In der JSON-Ausgabe siehst du sofort, ob NO ein Text oder false ist, ob die Postleitzahl ihre Null behalten hat und ob ein Schlüssel auf der falschen Ebene gelandet ist. Für Docker Compose macht docker compose config genau das: Es zeigt dir die Datei so, wie Compose sie verstanden hat.

Und eine Warnung zu Online-Konvertern: Konfigurationsdateien enthalten oft Passwörter, Tokens und interne Adressen. Die gehören nicht in ein Formular auf einer fremden Webseite. Die Befehle oben laufen lokal.

So schreibst du YAML ohne böse Überraschungen

Aus unseren Messungen ergeben sich sieben Regeln, die fast alle Probleme vermeiden:

  1. Alles in Anführungszeichen, was Text ist und wie etwas anderes aussieht. Ländercodes, Postleitzahlen, Versionen, Uhrzeiten, yes/no/on/off, Telefonnummern, Hashes, die nur aus Ziffern bestehen.
  2. Nur Leerzeichen, nie Tabs, und konsequent zwei Leerzeichen pro Ebene. Stell deinen Editor so ein, dass er Leerzeichen sichtbar macht.
  3. Einen Linter benutzen. yamllint meldet Tabs, Einrückungsfehler, doppelte Schlüssel und die gefährlichen Wahrheitswerte. Die Regel truthy warnt genau vor dem Norwegen-Problem.
  4. Wissen, welcher Parser liest. PyYAML (1.1) und js-yaml (1.2) verhalten sich bei derselben Datei unterschiedlich. Im Zweifel einmal nach JSON umwandeln und nachsehen.
  5. Fremdes YAML nur sicher laden. safe_load in Python, niemals unsafe_load oder load mit vollem Loader für Daten, die du nicht selbst geschrieben hast.
  6. Anker sparsam einsetzen und bei Daten aus fremden Quellen eine Bibliothek mit Alias-Limit wählen (wie yaml 2.x für Node).
  7. Schema prüfen. Viele Werkzeuge bieten JSON-Schemas für ihre YAML-Dateien an (Compose, GitHub Actions, Kubernetes). Editoren wie VS Code mit der YAML-Erweiterung zeigen Fehler dann schon beim Tippen.

Wann YAML, wann JSON? Die Entscheidung

Zwei leuchtende geometrische Podeste auf einem dunklen Boden, auf dem einen ein Stapel Würfel, auf dem anderen dünne durchscheinende Schichten

Nimm JSON, wenn:

  • Programme die Daten schreiben und lesen (APIs, Exporte, Caches, Logs, Nachrichten zwischen Diensten).
  • Die Daten groß sind oder oft gelesen werden.
  • Die Daten aus fremden oder unsicheren Quellen kommen.
  • Mehrere Programmiersprachen dieselbe Datei lesen und sich garantiert einig sein müssen.
  • Du im Browser arbeitest.

Nimm YAML, wenn:

  • Menschen die Datei schreiben und pflegen (Konfiguration, CI, Infrastruktur).
  • Du Kommentare brauchst, um Entscheidungen zu erklären.
  • Das Werkzeug es vorgibt (Compose, Kubernetes, GitHub Actions). Dann diskutiere nicht, sondern schreib sauberes YAML.
  • Mehrzeilige Texte wie Skripte oder Zertifikate Teil der Daten sind.

Denk über TOML nach, wenn: du ein neues Projekt startest, die Konfiguration flach bis mittelmäßig verschachtelt ist und du Kommentare willst, aber keine Typ-Raterei.

Englischsprachiger Direktvergleich von The Git Guild aus dem Jahr 2020. Ein älteres Video, die Unterschiede zwischen den Formaten haben sich seitdem aber nicht geändert.

Checkliste: YAML oder JSON in fünf Fragen

FrageEher YAMLEher JSON
Wer schreibt die Datei?ein Menschein Programm
Brauche ich Kommentare?janein
Wie groß sind die Daten?klein (Konfiguration)beliebig, auch sehr groß
Woher kommen die Daten?aus dem eigenen Repositoryauch von außen
Gibt das Werkzeug ein Format vor?Compose, Kubernetes, CIAPIs, Node-, PHP-, TS-Projekte

Wenn drei oder mehr Antworten in einer Spalte landen, ist die Entscheidung klar.

Häufige Fragen zu YAML vs JSON

Was ist der Unterschied zwischen YAML und JSON?

JSON ist ein strenges Datenformat mit Klammern und Anführungszeichen, das sich für den Austausch zwischen Programmen eignet. YAML strukturiert Daten über Einrückung, erlaubt Kommentare und mehrzeilige Texte und ist für von Menschen geschriebene Konfiguration gedacht. YAML errät Datentypen anhand des Werts, JSON legt sie eindeutig fest.

Ist YAML besser als JSON?

Nicht allgemein. YAML ist für Menschen angenehmer zu lesen und zu schreiben, JSON ist schneller, eindeutiger und sicherer. In unserem Test las JSON dieselben Daten 10- bis 220-mal schneller ein. Für Konfiguration ist YAML oft die bessere Wahl, für Daten und APIs JSON.

Ist JSON gültiges YAML?

Ja, seit YAML 1.2 ist jede gültige JSON-Datei auch gültiges YAML. Du kannst eine JSON-Datei also mit einem YAML-Parser einlesen. Bei älteren YAML-1.1-Parsern wie PyYAML kann es an seltenen Randfällen Abweichungen geben.

Was bedeutet YAML?

YAML steht heute rekursiv für „YAML Ain’t Markup Language“. Ursprünglich hieß es „Yet Another Markup Language“. Die Umbenennung sollte betonen, dass YAML ein Datenformat ist und keine Auszeichnungssprache wie HTML oder XML.

Was ist der Unterschied zwischen .yml und .yaml?

Es gibt keinen. Beide Dateiendungen bezeichnen dasselbe Format. Die offizielle Empfehlung ist .yaml, .yml stammt aus der Zeit, als Dateiendungen auf drei Zeichen beschränkt waren. Docker Compose sucht inzwischen bevorzugt nach compose.yaml.

Warum wird NO in YAML zu false?

Weil YAML 1.1 eine lange Liste von Wörtern als Wahrheitswerte deutet: yes, no, on, off, y, n in verschiedenen Schreibweisen. YAML 1.2 kennt nur noch true und false. Parser wie PyYAML folgen aber weiterhin 1.1. In unserem Test wurde der Ländercode NO dort zu false. Die Lösung sind Anführungszeichen: "NO".

Kann man in JSON Kommentare schreiben?

Nein, der JSON-Standard erlaubt keine Kommentare. Manche Werkzeuge akzeptieren die Variante JSONC mit //-Kommentaren, zum Beispiel VS Code und TypeScript für tsconfig.json. Wenn du regelmäßig Kommentare brauchst, ist YAML oder TOML meist das passendere Format.

Ist YAML schneller als JSON?

Nein, deutlich langsamer. In unserem Test mit 50.000 Datensätzen brauchte JSON.parse 30 ms, js-yaml 308 ms, die Bibliothek yaml 4,2 Sekunden und PyYAML in reinem Python 20 Sekunden. Bei kleinen Konfigurationsdateien spielt das keine Rolle, bei großen Datenmengen schon.

Ist YAML unsicher?

YAML selbst nicht, aber manche Parser-Funktionen. Mit yaml.unsafe_load in Python konnte unsere Testdatei einen Shell-Befehl auf dem Server ausführen. Außerdem können Anker und Aliase aus 254 Bytes über 22 MB Daten machen. Mit safe_load und Bibliotheken mit Alias-Limit ist YAML sicher nutzbar.

Wie wandle ich YAML in JSON um?

Lokal mit einem Einzeiler: in Python mit yaml.safe_load und json.dumps, in Node mit npx js-yaml datei.yaml, oder mit dem Werkzeug yq. Konfigurationsdateien mit Passwörtern solltest du nicht in Online-Konverter kopieren.

Warum benutzt Docker Compose YAML und nicht JSON?

Weil Compose-Dateien von Menschen geschrieben und gepflegt werden. Kommentare, mehrzeilige Befehle und Anker zur Wiederverwendung machen sie lesbarer als JSON. Compose akzeptiert übrigens auch JSON, weil JSON gültiges YAML ist. Praktisch nutzt das aber kaum jemand.

Fazit

Die Frage „YAML vs JSON“ ist eigentlich die Frage, wer die Datei schreibt. Unsere Messungen zeigen den Preis der YAML-Bequemlichkeit deutlich: 10- bis 220-mal langsameres Einlesen, drei Parser mit drei verschiedenen Ergebnissen für dieselbe Datei, ein Ländercode, der zu false wird, eine Uhrzeit, die zu 1342 wird, und eine 254-Byte-Datei, die zu 23 MB aufquillt. Dafür bekommst du Kommentare, mehrzeilige Texte und Dateien, die ein Mensch auf einen Blick versteht.

Unsere Empfehlung: JSON für Daten, YAML für Konfiguration. Und wenn du YAML schreibst, dann mit Anführungszeichen um alles, was wie etwas anderes aussehen könnte, mit einem Linter und mit safe_load. Wer das beherzigt, hat mit YAML ein angenehmes Format. Wer nicht, sucht irgendwann nach dem Fehler, warum Norwegen aus der Länderliste verschwunden ist.