JSON, YAML oder TOML: Welches Config-Format passt zu welchem Projekt?

Drei Buchstaben, drei Welten: JSON, YAML und TOML loesen alle dasselbe Problem -- strukturierte Daten in Textform -- aber sie machen es auf grundverschiedene Weise. Wer in einem Projekt das falsche Format waehlt, zahlt mit Bugs, Mergekonflikten und gefrusteten Kolleginnen. Wer das richtige waehlt, vergisst die Konfiguration und kann sich auf die eigentliche Arbeit konzentrieren. Dieser Vergleich zeigt mit echten Beispielen, harten Spezifikationen (RFC 8259, YAML 1.2.2, TOML 1.0.0) und einem klaren Entscheidungsbaum, wann welches Format das richtige ist -- und welche typischen Stolperfallen jedes mitbringt.

Drei Formate, drei Entstehungsgeschichten

JSON wurde Anfang der 2000er Jahre von Douglas Crockford aus einem Subset von JavaScript extrahiert und 2006 in RFC 4627 dokumentiert. Heute gilt RFC 8259 (2017) als die maßgebliche Beschreibung, parallel zu ECMA-404. Die Designidee: ein minimales, eindeutiges Format, das von jeder Programmiersprache geparst werden kann, ohne Mehrdeutigkeiten. JSON war nie als Format fuer von Menschen geschriebene Konfigurationen gedacht -- sondern als Datenaustauschformat zwischen Maschinen.

YAML startete 2001 als Reaktion auf XML und wurde von Clark Evans, Ingy doet Net und Oren Ben-Kiki entwickelt. Der Name -- urspruenglich Yet Another Markup Language, spaeter rekursiv YAML Aint Markup Language -- spiegelt den Anspruch wider, fuer Menschen lesbar zu sein. Die aktuelle Spezifikation YAML 1.2.2 (Oktober 2021) ist ein Superset von JSON. TOML (Toms Obvious Minimal Language) wurde 2013 von Tom Preston-Werner, dem Mitgruender von GitHub, vorgestellt, weil ihn YAML zu komplex und JSON fuer Konfigurationen zu strikt fand. Version 1.0.0 erschien im Januar 2021.

JSON: streng, schnell, maschinenfreundlich

JSON kennt sechs Typen: object, array, string, number, boolean und null. Das war es. Keine Kommentare, keine Trailing Commas, keine mehrzeiligen Strings, keine Datums- oder Zeittypen. Alle Strings muessen in doppelten Anfuehrungszeichen stehen, alle Schluessel ebenfalls. Diese Strenge ist gleichzeitig die groeßte Staerke und die groeßte Schwaeche: maschinenseitig ist JSON in unter 100 Zeilen Code parsebar, fuer Menschen ist es muehsam zu schreiben und unmoeglich zu kommentieren.

Genau deshalb dominiert JSON dort, wo Programme miteinander reden: REST-APIs, GraphQL-Responses, NoSQL-Datenbanken wie MongoDB, Web-Storage, Browserkommunikation. Wo JSON dagegen unangenehm wird: jede groeßere von Hand gepflegte Konfigurationsdatei. Genau das ist der Grund, warum Microsoft fuer die VS-Code-Settings JSONC eingefuehrt hat (JSON with Comments), und warum JSON5 als inoffizielle Erweiterung existiert. Beide sind aber kein Standard und werden von Standard-Parsern abgelehnt.

Das folgende Beispiel zeigt eine typische Datenbankkonfiguration mit Feature-Flags in JSON:

{
  "database": {
    "host": "db.example.com",
    "port": 5432,
    "user": "app",
    "password": "s3cret",
    "ssl": true
  },
  "features": [
    "dark_mode",
    "beta_search",
    "new_checkout"
  ],
  "timeout_ms": 5000
}

Auffaellig: keine Kommentare moeglich, das letzte Listenelement darf kein Komma haben, jeder Schluessel braucht Anfuehrungszeichen. Wer hier von Hand eine Zeile loescht und das Komma vergisst, bekommt vom Parser eine kryptische Fehlermeldung statt einer hilfreichen.

YAML: maximal lesbar, maximal stolperreich

YAML setzt auf Einrueckung statt geschweifte Klammern, kennt Kommentare mit #, mehrzeilige Strings mit | (literal) oder > (folded), Anker (&name) und Aliasse (*name) fuer Wiederverwendung sowie Merge-Keys (<<:). Listen werden mit Bindestrich, Maps mit Doppelpunkt geschrieben. Wer YAML kennt, schreibt damit einen Kubernetes-Manifest in der Haelfte der Zeit, die JSON brauchen wuerde.

Genau diese Bequemlichkeit ist auch der Grund fuer eine lange Reihe beruechtigter Bugs. YAML versucht Typen automatisch zu erraten -- und liegt dabei manchmal grandios falsch. Die Spezifikation hat in 1.2 nachgebessert, aber sehr viele Tools laufen immer noch auf 1.1-Parsern.

Dieselbe Konfiguration in YAML, mit einem Anker zur Wiederverwendung:

# Datenbank-Verbindung
database:
  host: db.example.com
  port: 5432
  user: app
  password: s3cret
  ssl: true

# Aktive Feature-Flags
features:
  - dark_mode
  - beta_search
  - new_checkout

timeout_ms: 5000

Die typischen YAML-Stolperfallen, jede einmal in echten Production-Outages aufgetaucht:

  • Das Norwegen-Problem: In YAML 1.1 wird NO als boolean false interpretiert. Eine Liste von Laendercodes countries: [DE, FR, NO, IT] verwandelte sich in ["DE", "FR", false, "IT"]. Loesung: Strings explizit quoten oder YAML 1.2 nutzen.
  • Versionsnummern als Zahlen: version: 1.10 wird als Float 1.1 geparst, nicht als String. Wer Semver-Versionen unquoted speichert, verliert Stellen.
  • Tabs sind verboten: YAML akzeptiert ausschließlich Leerzeichen zur Einrueckung. Ein Editor, der heimlich Tabs einfuegt, bricht die Datei -- die Fehlermeldung ist meist nutzlos.
  • Trailing Whitespace und Encoding: ein nicht sichtbares Leerzeichen am Zeilenende kann Block-Strings stillschweigend abschneiden. CRLF vs LF macht in einigen Parsern einen Unterschied.

TOML: explizit, typsicher, unmissverstaendlich

TOML wurde mit einem klaren Designziel entworfen: minimaler, leicht lesbarer, eindeutig parsebarer Konfigurationsformat ohne YAML-Stolperfallen. Schluessel werden ohne Anfuehrungszeichen geschrieben, Strings explizit, Sektionen mit eckigen Klammern. TOML hat starke Typen: integer, float, boolean, string, datetime (RFC 3339), array und table. Datum und Uhrzeit sind nativ -- das ist in JSON und YAML 1.2 keine Selbstverstaendlichkeit.

Besonders praktisch: Array of Tables mit doppelten eckigen Klammern [[users]] -- damit lassen sich Listen von Objekten schreiben, ohne dass die Einrueckung explodiert. TOML eignet sich exzellent fuer flache bis mittel-verschachtelte Konfigurationen. Bei sehr tiefen Strukturen wird es allerdings unleserlich, weil die volle Sektion bei jedem Block ausgeschrieben werden muss.

Dieselbe Konfiguration in TOML:

# Datenbank-Verbindung
[database]
host = "db.example.com"
port = 5432
user = "app"
password = "s3cret"
ssl = true

# Aktive Feature-Flags
features = [
  "dark_mode",
  "beta_search",
  "new_checkout",
]

timeout_ms = 5000

Auffaellig im Vergleich: Trailing Commas sind in TOML erlaubt (wie in Python), Kommentare beginnen mit #, Strings sind immer gequoted, Sektionsueberschriften machen den Datenbankblock visuell klar. Genau dieses Format hat sich in Rust (Cargo.toml) und Python (pyproject.toml) durchgesetzt -- nicht aus Mode, sondern weil es bei mittelgroßen Konfigurationen die wenigsten Bugs produziert.

Entscheidungsbaum: welches Format wann?

Die Wahl ist kein Geschmacksstreit, sondern eine technische Entscheidung. Vier Faustregeln, die sich in der Praxis bewaehren:

  • Maschine-zu-Maschine-API oder Datenaustausch ueber HTTP: immer JSON. Es ist der gemeinsame Nenner, wird von jeder Sprache nativ unterstuetzt, und Performance schlaegt Komfort, wenn nie ein Mensch die Daten ansieht.
  • DevOps und Infrastruktur (Kubernetes, Helm, Ansible, GitHub Actions, Docker Compose): YAML. Nicht weil es perfekt waere, sondern weil der gesamte Werkzeugkasten dorthin geht. Hier hilft kein Streit -- dafuer Linter und Schema-Validierung.
  • Anwendungs-Konfiguration mit menschlicher Pflege: TOML. Klar lesbar, schwer falsch zu schreiben, native Datums-, Booleans- und Integer-Typen. Ideal fuer CLI-Tools, Desktop-Apps, Build-Systeme.
  • Folge dem Ecosystem: Rust-Projekt -> TOML. Helm-Chart -> YAML. JavaScript-Tool -> JSON oder TOML. Nicht jede Entscheidung muss neu getroffen werden -- konsistente Tools wiegen schwerer als persoenliche Praeferenz.

Performance: warum JSON gewinnt, wenn es zaehlt

Parsen ist kein hoeflicher Wettbewerb. Benchmarks aus den Standardbibliotheken von Python, Go und Rust zeigen JSON-Parser durchgehend um den Faktor 5 bis 10 schneller als YAML-Parser auf gleich großen Dokumenten. Der Grund: JSON kennt nur sechs Typen ohne automatische Typ-Erkennung, keine Anker, keine mehrzeiligen Block-Scalars. TOML liegt in der Mitte -- merklich schneller als YAML, etwas langsamer als JSON.

Praktisch heißt das: fuer eine Service-Konfiguration mit 200 Zeilen, die beim Start einmal gelesen wird, ist Performance egal. Fuer eine API, die JSON-Bodies in Millionen Requests pro Tag parst, sind 5x bis 10x ein hartes Geschaeftsargument -- das ist genau der Grund, warum niemand YAML als API-Format vorschlaegt. Wer ein Tool wie den YAML-JSON-Konverter benutzt, um YAML-Configs einmal zu serialisieren und dann als JSON auszuliefern, schiebt diesen Overhead aus dem Hot Path heraus.

Schema-Validierung: wer pruefen will, was er liest

JSON Schema (aktuell Draft 2020-12) ist der ausgereifteste Standard fuer strukturelle Validierung. Implementierungen gibt es in allen Hauptsprachen, Editor-Integration (VS Code, JetBrains) liefert Autocomplete fuer komplexe Configs. YAML nutzt typischerweise dieselben Schemas, weil YAML 1.2 strikt JSON-kompatibel ist -- die Validierung passiert nach dem Parsen.

TOML hat aktuell keinen weit verbreiteten Schema-Standard. Es gibt taplo (eine TOML-Toolchain mit Schema-Unterstuetzung ueber JSON Schema), aber das ist kein Ersatz fuer ein verbindlich versioniertes Schema-Format wie bei JSON. Fuer Konfigurationen, die zwingend strukturell validiert werden muessen (z. B. von einem CI-System), ist das ein echter Nachteil -- in der Praxis loesen viele Projekte das, indem sie TOML beim Build in JSON konvertieren und dann gegen ein JSON Schema validieren.

Werkzeuge: ein kurzer Reiseflyer

Welches Format auch immer du gewaehlt hast -- die richtige Toolchain spart Stunden. Diese vier sind eingespielter Standard:

  • jq ist das Schweizer Taschenmesser fuer JSON in der Shell. Filtern, transformieren, mit jq -r rohen Text ausgeben. Wer einmal jq gelernt hat, schreibt nie wieder ein Shell-Skript mit grep ueber JSON.
  • yq ist das Gegenstueck fuer YAML, mit aehnlicher Syntax und konvertierbarem Output zu JSON. Zwei Varianten existieren (yq von mikefarah und kislyuk yq) -- die Syntax unterscheidet sich leicht, in den meisten Projekten reicht mikefarah-yq.
  • taplo formatiert, validiert und beautyfied TOML. Mit Schema-Support, LSP-Integration und CLI -- ein No-Brainer fuer jedes TOML-Projekt jenseits eines einzelnen Cargo.toml.
  • Fuer schnelle Browser-Konvertierungen ohne lokale Installation: der YAML-JSON-Konverter, der JSON-Formatter und der CSV-zu-JSON-Konverter auf CalcSI laufen vollstaendig client-seitig -- nichts verlaesst deinen Browser.

Haeufige Fragen

Warum nutzt Kubernetes YAML, wenn es so viele Stolperfallen hat?

Historisch und pragmatisch. Als Kubernetes 2014/15 entstand, war YAML im Cloud-Native-Bereich bereits Standard (Puppet, Chef, Ansible). Außerdem ist Kubernetes-Konfiguration tief verschachtelt -- ein Helm-Chart mit 500 Zeilen YAML waere als JSON etwa 800 Zeilen lang. Die Loesung der Community ist nicht, das Format zu wechseln, sondern Tooling drumherum zu bauen: Schemas (kubectl explain, kube-linter), Templates (Helm, Kustomize) und Validatoren (conftest, datree). Wer Kubernetes-YAML schreibt, sollte die typischen Fallen kennen -- der YAML-JSON-Konverter hilft beim schnellen Cross-Check eines Manifests.

Kann ich Kommentare in JSON benutzen?

Nicht im Standard. RFC 8259 erlaubt keine Kommentare, Punkt. Es gibt zwei populaere Erweiterungen: JSONC (JSON with Comments, eingefuehrt von VS Code) erlaubt // und /* */. JSON5 geht weiter und erlaubt Trailing Commas, unquoted Keys, Hex-Literale. Beide sind nuetzlich, aber kein offizielles JSON -- der eingebaute Parser einer Sprache wird sie zurueckweisen. Wer Kommentare braucht und das Format frei waehlen kann, nimmt besser TOML oder YAML.

Warum reicht das alte INI-Format eigentlich nicht?

INI hat keine standardisierte Spezifikation -- jeder Parser behandelt Kanten anders. Wichtiger: INI kann nicht verschachteln. Eine Liste von Datenbanken mit jeweils Host, Port und Credentials ist in INI nicht sauber darstellbar; man landet bei Krueckenkonstrukten wie db1_host, db1_port, db2_host. Genau diese Luecke schliesst TOML, das oft als INI mit Typen und Spezifikation beschrieben wird -- eindeutig, verschachtelbar, mit klaren Datentypen, ohne YAML-Komplexitaet.

Hinweis: Dieser Artikel ist eine technische Uebersicht und ersetzt nicht das Studium der jeweiligen Spezifikationen. Spezifikations-Details aendern sich -- pruefe immer die aktuelle Version (RFC 8259, YAML 1.2.2, TOML 1.0.0) bei sicherheitsrelevanten oder produktionskritischen Entscheidungen.

Kommentare