Zum Hauptinhalt springen

developer-tools

YAML vs JSON vs TOML: Wann Welches Konfigurationsformat Verwenden

robinhood-projects11 Min. Lesezeit

JSON-Betrachter, Formatierer & Editor

JSON im interaktiven Live-Baum anzeigen, bearbeiten und formatieren. Inline-Bearbeitung von Werten, Umbenennen von Schlüsseln, Knoten hinzufügen/entfernen, JSONC-Kommentarunterstützung und Ein-Klick-Export — vollständig im Browser.

Tool verwenden →

CSV-Viewer & Smart Table

Öffne jede CSV als interaktive Smart Table: Spalten sortieren, Zeilen filtern, Zellen live bearbeiten und als CSV, XLS oder XLSX exportieren. Komplett im Browser, kein Konto erforderlich.

Tool verwenden →

YAML vs JSON vs TOML: Wann Welches Konfigurationsformat Verwenden

Jedes Projekt hat irgendwann ein Konfigurationsproblem. Du musst Datenbankzugangsdaten speichern, Deployment-Umgebungen definieren, eine CI-Pipeline beschreiben oder Abhängigkeiten verknüpfen — und jemand muss ein Format wählen. JSON? YAML? TOML? Die Wahl fühlt sich willkürlich an, bis sie dich beißt.

Docker Compose-Dateien sind YAML. package.json ist JSON. Rusts Abhängigkeitsmanifest (Cargo.toml) ist TOML. Python-Packaging (pyproject.toml) ist TOML. GitHub Actions-Workflows sind YAML. Das ist nicht zufällig — jedes Format hat die Adoptionsschlacht in seiner Domäne aus spezifischen Gründen gewonnen. Diese Gründe zu verstehen ermöglicht es dir, eine bewusste Entscheidung zu treffen, statt standardmäßig „was auch immer das Template benutzte" zu nehmen.

Dieser Artikel ist ein Entscheidungsleitfaden. Am Ende wirst du die echten Abwägungen jedes Formats kennen, die genauen YAML-Footguns sehen, die Produktionsvorfälle verursacht haben, und einen klaren Rahmen für die Wahl haben.


Der Gemeinsame Vorfahre: INI-Dateien

Bevor wir in die modernen Kandidaten eintauchen, lohnt es sich, dreißig Sekunden mit INI-Dateien zu verbringen — dem Format, auf das alle drei in gewisser Weise reagieren.

INI-Dateien sehen so aus:

[database]
host = localhost
port = 5432
name = mydb
 
[server]
port = 8080
debug = true

Einfach, von Menschen lesbar, unterstützt Abschnitte, unterstützt Kommentare. Die Probleme sind ebenso einfach: keine Standardspezifikation (jeder Parser interpretiert Randfälle anders), keine verschachtelten Strukturen über eine Ebene hinaus, keine Arrays, keine expliziten Typen. Alles ist ein String, es sei denn, deine Anwendung entscheidet anders.

INI war in Ordnung für php.ini im Jahr 1997. Es ist nicht in Ordnung für die Beschreibung eines Kubernetes-Deployments im Jahr 2026. Aber es identifizierte die richtigen Ziele — menschliche Editierbarkeit und Kommentare — die die modernen Formate entweder geerbt oder verworfen haben.


JSON: Die Lingua Franca der Daten

JSON (JavaScript Object Notation) wurde Anfang der 2000er Jahre standardisiert und wurde das dominante Wire-Format für APIs. Seine Stärke kommt von seinen Einschränkungen.

Was JSON richtig macht

JSON hat genau sechs Werttypen: String, Zahl, Boolean, null, Array und Objekt. Die Spezifikation ist eindeutig. Jeder konforme JSON-Parser wird dasselbe Dokument identisch parsen. Keine Überraschungen.

{
  "database": {
    "host": "localhost",
    "port": 5432,
    "ssl": true
  },
  "allowed_origins": ["https://example.com", "https://api.example.com"],
  "timeout_ms": null
}

Der Typ von port ist eindeutig eine Zahl. ssl ist eindeutig ein Boolean. allowed_origins ist eindeutig ein Array von Strings. Ein JSON-Parser kann das nicht falsch lesen.

JSON ist auch allgegenwärtig. Jede Sprache hat einen Standard-Bibliotheks-JSON-Parser. Browser parsen es nativ. Datenbanken wie PostgreSQL haben native JSON-Spalten. Es ist das kleinste-gemeinsame-Nenner-Format für den Datenaustausch zwischen Systemen, die keine Laufzeitumgebung teilen.

Was JSON für Konfiguration falsch macht

JSON hat keine Kommentarsyntax. Das ist eine bewusste Designentscheidung von Douglas Crockford (dem Schöpfer von JSON), mit der Begründung, dass Kommentare in Datenformaten Menschen ermutigen, Parsing-Direktiven hineinzuschreiben, was die Portabilität des Formats korrumpiert.

Das ist ein gutes Prinzip für API-Antworten. Es ist ein ernstes Problem für Konfigurationsdateien. Konfigurationsdateien brauchen Kommentare. Du musst erklären, warum timeout_ms 30000 und nicht 10000 ist. Du musst markieren, welche Felder sicher zu ändern sind. Du musst eine Notiz hinterlassen, die sagt „setze das nicht über 100 in Staging."

Die Workarounds sind alle schlecht. Manche Teams verwenden "_comment"-Felder. Manche verwenden JSON5 (ein Superset mit Kommentaren) und hoffen, dass ihre Tooling es handhabt. Manche verwenden JSONC (JSON with Comments, popularisiert durch VS Codes settings.json). Keines davon ist Standard-JSON.

JSON ist auch ausführlich für Konfiguration. Abschließende Kommas sind nicht erlaubt, was beim Neuanordnen von Feldern ständig Syntaxfehler verursacht. Jeder String-Schlüssel erfordert doppelte Anführungszeichen. Es gibt keine mehrzeilige String-Syntax — ein langer Shell-Befehl muss auf eine Zeile gequetscht werden.

JSON gehört in: API-Antworten, Datenaustausch zwischen Diensten, Package-Manifeste, die hauptsächlich maschinell geschrieben werden (package.json, composer.json), und überall, wo du garantierte Parse-Konsistenz über heterogene Systeme hinweg benötigst.

Du kannst JSON online validieren, um Syntaxfehler zu erkennen, bevor sie deine Anwendung erreichen — was wichtiger ist, als du vielleicht erwartest, da ein einzelnes fehlendes Komma oder eine überflüssige schließende Klammer einen JSON-Parser vollständig kaputtmacht.


YAML: Macht und Gefahr

YAML (YAML Ain't Markup Language) wurde als menschenfreundliche Alternative zu XML entworfen. Es ist ausdrucksstark, lesbar und wird in DevOps-Tooling umfangreich eingesetzt. Es ist auch das gefährlichste Konfigurationsformat in gängigem Einsatz.

Was YAML richtig macht

YAML erlaubt Kommentare (#). Es leitet Typen aus Werten ohne Anführungszeichen ab, sodass du port: 5432 statt "port": 5432 schreiben kannst. Es unterstützt mehrzeilige Strings mit sauberer heredoc-ähnlicher Syntax. Es ist prägnant: Einrückung ersetzt geschweifte und eckige Klammern.

database:
  host: localhost
  port: 5432
  ssl: true
 
allowed_origins:
  - https://example.com
  - https://api.example.com
 
# Das ist ein Kommentar, der erklärt, warum das Timeout hoch ist
timeout_ms: 30000

Für CI/CD-Konfigurationen — GitHub Actions, GitLab CI, CircleCI — ist YAMLs Fähigkeit, verschachtelte Strukturen sauber mit Kommentaren auszudrücken, genuinely nützlich. Eine GitHub Actions-Workflow-Datei erstreckt sich oft über Hunderte von Zeilen mit verschachtelten Bedingungen, Matrix-Strategien und Umgebungsvariablen-Blöcken. JSON wäre unlesbar. TOML wäre für tief verschachtelte Strukturen unhandlich.

Die YAML-Footguns

YAMLs Typinferenz ist der Punkt, an dem es schiefläuft. Der Parser schaut auf Werte ohne Anführungszeichen und entscheidet, welcher Typ sie sind. Die Entscheidungen, die er trifft, entsprechen nicht immer dem, was du erwartest.

Das Norwegen-Problem. In YAML 1.1 (was die meisten Parser implementieren — nicht YAML 1.2) wird ein nacktes NO als der Boolean false geparst. Dasselbe gilt für no, No, n, N, false, False, FALSE, off, Off und OFF. Eine Liste von ISO 3166-1-Ländercodes enthält NO für Norwegen. Eine Konfigurationsdatei mit einer Ländercodes-Liste wird Norwegen stillschweigend zu false machen.

# YAML 1.1 — was der Parser tatsächlich sieht
country: NO        # → false (Boolean)
enabled: yes       # → true (Boolean)
mode: on           # → true (Boolean)
debug: off         # → false (Boolean)

Die Lösung ist, alles, was ein String sein soll, in Anführungszeichen zu setzen: country: "NO". Aber der ganze Reiz von YAML ist, dass man Dinge nicht in Anführungszeichen setzen muss. Anführungszeichen zu erfordern, um Überraschungen zu vermeiden, erodiert den Lesbarkeits-Vorteil des Formats.

Oktale Ganzzahlen. In YAML 1.1 wird eine Zahl, die mit 0 beginnt, als oktal behandelt. Dateiberechtigungen werden häufig in Oktal geschrieben: chmod: 0755. Ein YAML-Parser liest 0755 als die Dezimalzahl 493, nicht 755. Das hat echte Deployment-Skripte kaputt gemacht.

# YAML 1.1 — oktale Interpretation
file_mode: 0755    # → 493 (Dezimaläquivalent von oktal 0755)

Mehrzeilige String-Ambiguität. YAML bietet mehrere mehrzeilige String-Syntaxen — Literal-Block (|), gefalteter Block (>), und inline. Sie verhalten sich unterschiedlich bezüglich Zeilenumbrüchen, abschließenden Leerzeichen und Einrückung. Die falsche zu wählen produziert stillschweigend den falschen String.

# Literal-Block — bewahrt Zeilenumbrüche
command: |
  npm install
  npm run build
 
# Gefalteter Block — Zeilenumbrüche werden zu Leerzeichen (nützlich für langen Text)
description: >
  Das ist eine lange Beschreibung, die
  zu einer einzelnen Zeile mit Leerzeichen gefaltet wird.

Tabs vs. Leerzeichen. YAML erlaubt keine Tab-Zeichen für Einrückung. Ein Editor, der stillschweigend Tabs einfügt, produziert einen Parse-Fehler — oder schlimmer, einen anderen Parse abhängig von der Tab-Stop-Einstellung.

YAML 1.2 hat viele dieser Probleme behoben (einschließlich der Boolean-Wert-Liste), aber die meisten Tools implementieren noch 1.1. Wenn du YAML verwendest, schreibst du für den Parser, den deine Toolchain zufällig mitbringt, was mit deinen Annahmen übereinstimmen kann oder nicht.


TOML: Für Konfiguration Entworfen

TOML (Tom's Obvious Minimal Language) wurde 2013 von Tom Preston-Werner (Mitgründer von GitHub) speziell als Konfigurationsdateiformat erstellt, das Menschen schreiben und Maschinen ohne Mehrdeutigkeit parsen können.

Was TOML richtig macht

TOML hat explizite, eindeutige Typen. Ein String ist immer in Anführungszeichen. Eine Zahl ist immer eine Zahl. Ein Boolean ist immer true oder false (Kleinschreibung, keine Aliase). Es gibt keine Typinferenz aus Werten ohne Anführungszeichen, also kein Norwegen-Problem.

[database]
host = "localhost"
port = 5432
ssl = true
 
allowed_origins = [
  "https://example.com",
  "https://api.example.com",
]
 
# Das ist ein Kommentar, der erklärt, warum das Timeout hoch ist
timeout_ms = 30000

TOML hat erstklassige Unterstützung für Daten und Zeiten (publishedAt = 2026-04-04), die JSON und YAML als Strings belassen, die Anwendungen selbst parsen.

Abschnittsköpfe ([database], [[servers]]) sind explizit und lesbar. Punkt-getrennte Schlüssel (database.host = "localhost") erlauben dir, verschachtelte Werte inline auszudrücken. Array of Tables ([[servers]]) gibt dir eine saubere Liste-von-Objekten-Syntax.

[[servers]]
name = "production"
host = "prod.example.com"
port = 443
 
[[servers]]
name = "staging"
host = "staging.example.com"
port = 443

Die TOML-Spezifikation ist präzise und versioniert. Jeder konforme TOML-Parser produziert für dieselbe Eingabe dasselbe Ergebnis.

Wo TOML Schwächen Hat

TOML funktioniert gut für flache bis moderate Verschachtelung. Für tief verschachtelte Strukturen — die Art, die in Kubernetes-Manifesten oder Ansible-Playbooks erscheinen — wird die Abschnittskopf-Syntax repetitiv. YAMLs einrückungsbasierte Verschachtelung skaliert natürlicher auf sechs oder sieben Ebenen tief.

TOML hat auch weniger Tooling-Unterstützung als JSON oder YAML. Die meisten Sprachen haben hervorragende TOML-Bibliotheken, aber die Editor-Unterstützung (Syntaxhervorhebung, Validierung, Autovervollständigung) ist weniger konsistent als bei JSON.


Vergleichstabelle

MerkmalJSONYAMLTOMLINI
KommentareNeinJa (#)Ja (#)Ja (; oder #)
Explizite TypenJaNein (inferiert)JaNein (alle Strings)
Mehrzeilige StringsNein (nur Escape)Ja (mehrere Syntaxen)Ja (""")Nein
Verschachtelte StrukturenJa (ausführlich)Ja (prägnant)Ja (moderat)Nur eine Ebene
Parsing-Ambiguität-RisikoNiedrigHochSehr niedrigMittel
Menschliche SchreibbarkeitMittelHochHochHoch
MaschinengenerierungAusgezeichnetGutGutSchlecht
Häufige VerwendungenAPIs, ManifesteCI/CD, OrchestrierungProjektkonfigurationLegacy-App-Konfiguration

Der Entscheidungsrahmen

Wenn du die Marketingsprache weglässt, reduziert sich die Wahl auf drei Fragen.

Wird das hauptsächlich maschinell generiert oder von Menschen geschrieben?

Wenn die Datei von Code generiert und von Code konsumiert wird — eine API-Antwort, ein Build-Artefakt, ein serialisierter Cache-Eintrag — verwende JSON. Es ist das portabelste, das am besten parsbare, und Tooling-Unterstützung ist universell. Du brauchst keine Kommentare in einer Datei, die kein Mensch liest. Diese JSON-Dateien zu komprimieren vor der Übertragung über ein Netzwerk kann die Payload-Größe bedeutend reduzieren.

Wenn ein Mensch diese Datei regelmäßig schreibt und bearbeitet — eine Projektkonfiguration, eine Umgebungsbeschreibung, ein Tool-Manifest — sind Kommentare nicht verhandelbar. Das schließt reines JSON aus.

Kontrollierst du die Toolchain?

Wenn du in einem Ökosystem feststeckst, das ein Format vorschreibt — Kubernetes verlangt YAML, GitHub Actions verlangt YAML, Cargo verlangt TOML, package.json ist JSON — gibt es keine Entscheidung zu treffen. Verwende, was das Ökosystem erwartet.

Wenn du ein neues Tool oder eine neue Konfigurationsdatei von Grund auf entwirfst, hast du eine echte Wahl.

Wie tief ist die Verschachtelung, und wie tolerant ist dein Team gegenüber subtilen Bugs?

YAML ist ausdrucksstark aber fragil. Ein Team, das sorgfältiges YAML schreibt, alle Strings in Anführungszeichen setzt, einen Linter ausführt und den Unterschied zwischen 1.1 und 1.2 versteht, kann es sicher verwenden. Ein Team, das sich schnell bewegt, diverse Editor-Setups hat und kein YAML-Linting in CI ausführt, wird irgendwann ein Norwegen-Problem oder einen Oktal-Bug in Produktion haben.

TOML ist die sicherere Wahl für von Menschen geschriebene Konfiguration, wenn du das Format kontrollierst. Explizite Typen bedeuten, dass der Parser-Fehler zur Parse-Zeit erscheint, nicht zur Laufzeit, wenn Norwegen zu false geworden ist und deine Feature-Flag-Logik stillschweigend fehlschlägt.

Schnellreferenz

  • API-Antwort oder Datenaustausch zwischen Diensten: JSON
  • Package-Manifest (hauptsächlich maschinell geschrieben): JSON
  • Kubernetes, Docker Compose, GitHub Actions, Ansible: YAML (keine Wahl)
  • Neue Projektkonfigurationsdatei, die du entwirfst: TOML
  • Rust-Projekt: TOML (Cargo.toml)
  • Python-Projekt: TOML (pyproject.toml)
  • Legacy-Anwendungskonfiguration mit einfachen Schlüssel-Wert-Anforderungen: INI (oder nach TOML migrieren)

Deine Konfigurationsdateien Validieren

Syntaxfehler in Konfigurationsdateien sind einige der frustrierendsten Bugs, die man diagnostizieren muss — die Anwendung startet nicht, die Fehlermeldung ist kryptisch und der Fehler ist ein einzeln fehlplatziertes Zeichen.

Für JSON kannst du JSON online validieren und schön formatieren, um Fehler sofort zu erkennen. Eine JSON-Konfigurationsdatei vor dem Commit in einen Validator einzufügen dauert fünf Sekunden und verhindert eine Klasse von CI-Fehlern. Für tiefere JSON-Workflows — Minifizierung für Produktion, Diff von Config-Änderungen zwischen Umgebungen — sieh dir unsere Anleitung über wie man JSON validiert, minifiziert und schön formatiert an.

Für YAML ist yamllint der Standard-CLI-Linter. Es in CI auszuführen ist nicht optional, wenn dein Team Produktions-YAML schreibt. Für TOML werden in den meisten Sprach-Ökosystemen eingebaute Validatoren mitgeliefert (cargo check validiert Cargo.toml implizit; python -c "import tomllib; tomllib.load(open('pyproject.toml', 'rb'))" validiert jede TOML-Datei direkt).


Das Format Ist ein Vertrag

Welches Format du auch wählst, es wird zu einem Vertrag mit jedem Entwickler und Tool, das dein Projekt berührt. Es später zu ändern ist schmerzhaft — nicht unmöglich, aber schmerzhaft. Die Migration von setup.cfg und setup.py zu pyproject.toml im Python-Ökosystem dauerte Jahre und ist noch nicht abgeschlossen.

Wähle bewusst. JSON, wenn Maschinen der primäre Konsument sind und Portabilität kritisch ist. YAML, wenn das Ökosystem es vorschreibt oder wenn tief verschachtelte Strukturen lesbar sein müssen. TOML, wenn Menschen die Datei schreiben, Korrektheit wichtig ist und du möchtest, dass der Parser Mehrdeutigkeit zur Lesezeit erkennt, anstatt dass sie sechs Monate später als Laufzeit-Bug auftaucht.

Das Konfigurationsformat ist nicht nur ein Dateiformat. Es ist eine Aussage darüber, wer die Datei bearbeitet, welche Tools sie verarbeiten und wie viel du impliziter Typumwandlung vertraust. Mache diese Aussage mit Absicht.


Musst du jetzt eine JSON-Konfigurationsdatei validieren? Probiere den FileCrank JSON Viewer — füge dein JSON ein, erkenne Fehler sofort und formatiere es für Lesbarkeit.