Jedes Projekt braucht Konfiguration, und Sie haben drei Hauptoptionen: JSON, YAML oder TOML. Ich habe alle drei ausgiebig verwendet, und jedes treibt mich auf unterschiedliche Weise in den Wahnsinn. Hier ist meine ehrliche Einschätzung, wann man was verwenden sollte.

JSON: Der Universalsoldat

Sie kennen JSON bereits. Es ist überall. Jede Sprache kann es parsen. Aber seien wir ehrlich über seine Schwächen als Config-Datei:

  • Keine Kommentare. Sie können buchstäblich nicht erklären, was eine Einstellung bewirkt. Das ist absurd für eine Konfigurationsdatei.
  • Keine Trailing-Kommas. Neue Zeile am Ende hinzufügen, Komma in der vorherigen Zeile vergessen — und Ihre Config ist kaputt.
  • Überall Anführungszeichen. Jeder Schlüssel braucht doppelte Anführungszeichen: {"port": 8080} statt einfach port: 8080.

Trotz alledem wird JSON für Konfiguration verwendet von npm (package.json), TypeScript (tsconfig.json), VS Code (settings.json) und mehr. Der Grund? Null Mehrdeutigkeit. JSON ist so strikt, dass es nur eine einzige Interpretation gibt.

YAML: Schön aber gefährlich

YAML sieht großartig aus. Sauber, minimal, menschenlesbar. Aber es hat einige berüchtigte Fallstricke:

yaml

Das ist das „Norwegen-Problem", das ich im YAML-Artikel erwähnt habe. YAML 1.1 behandelt NO, YES, ON, OFF als Booleans. Das wurde in YAML 1.2 behoben, aber viele Parser verwenden immer noch standardmäßig das 1.1-Verhalten.

Dazu kommt die Einrückungsempfindlichkeit. Ein einziges verrutschtes Leerzeichen kann die Bedeutung Ihrer Datei komplett ändern — und die Fehlermeldung wird schrecklich sein.

Dennoch ist YAML der Standard für Docker Compose, Kubernetes, GitHub Actions und Ansible. Wenn Sie im DevOps/Cloud-Bereich arbeiten, ist YAML-Kompetenz Pflicht.

TOML: Der Konfigurationsspezialist

TOML (Tom's Obvious Minimal Language) wurde speziell für Konfiguration entworfen. Es zielt darauf ab, offensichtlich zu sein — das heißt, es gibt (fast) keine Möglichkeit, eine TOML-Datei falsch zu lesen.

So sieht eine TOML-Konfiguration aus:

toml

Was TOML richtig gut macht: native Datum/Zeit-Typen (created = 2026-03-08T10:30:00Z), keine Einrückungsprobleme, Kommentare mit # und eine Syntax, die wirklich schwer falsch zu machen ist.

Der Nachteil? Tief verschachtelte Strukturen werden wortreich. TOML ist großartig für flache Konfigurationen, aber wenn Sie fünf Ebenen der Verschachtelung brauchen, sind YAML oder JSON möglicherweise lesbarer.

TOML wird von Rust (Cargo.toml), Python (pyproject.toml), Hugo und einer wachsenden Zahl von Tools verwendet.

Meine Empfehlungen

SzenarioWahlGrund
Maschinell generierte ConfigJSONAm striktesten, kompatibelsten
DevOps/InfrastrukturYAMLÖkosystem erwartet es
App-KonfigurationTOMLKommentare + minimale Mehrdeutigkeit
Einfache Schlüssel-Wert-EinstellungenTOMLAm saubersten für flache Configs
Komplexe verschachtelte StrukturenYAMLBeste verschachtelte Syntax

Fazit

Dieselbe Config in allen drei Formaten

Wenn man dieselben Daten in allen drei Formaten sieht, werden die Unterschiede richtig deutlich. Hier ist eine einfache App-Konfiguration:

JSON:

json

YAML:

yaml

TOML:

toml

Beachten Sie, wie JSON all diese Anführungszeichen und geschweiften Klammern braucht, YAML am kürzesten ist aber auf Einrückung angewiesen, und TOML einen Mittelweg mit expliziten Abschnittsüberschriften und ohne Einrückungsabhängigkeit findet.

Häufige Fehler in Config-Dateien

YAML: Versehentliche Typumwandlung. Über das Norwegen-Problem hinaus interpretiert YAML auch 3.10 als die Zahl 3.1 (die nachgestellte Null wird verworfen) und 1_000 als 1000. Wenn Ihre Config-Werte Versionsstrings wie 3.10 sind, setzen Sie sie immer in Anführungszeichen: version: "3.10".

JSON: Vergessen, dass die Reihenfolge keine Rolle spielt. JSON-Objekte sind laut Spezifikation ungeordnet. Wenn Ihre Config-Verarbeitung von der Schlüsselreihenfolge abhängt, bauen Sie auf einem fragilen Fundament. Manche Parser bewahren die Einfügereihenfolge, andere nicht.

TOML: Verwirrung mit Arrays von Tabellen. TOML verwendet [[doppelte.Klammern]] für Arrays von Tabellen, was Anfänger stolpern lässt. So definieren Sie mehrere Server:

toml

Umgebungsspezifische Configs

Ein Bereich, in dem alle drei Formate Schwierigkeiten haben, ist die Handhabung umgebungsspezifischer Überschreibungen (Dev vs. Staging vs. Production). Gängige Lösungen sind:

  • Mehrere Dateien: config.base.yaml + config.production.yaml mit Deep Merging
  • Umgebungsvariablen-Interpolation: Einige YAML-Tools unterstützen ${DB_HOST}-Syntax, aber das ist nicht standardisiert
  • Externe Tools: Doppler, HashiCorp Vault oder Cloud-native Config-Dienste

Persönlich bevorzuge ich einen einfachen Ansatz: eine Config-Datei mit sinnvollen Standardwerten und Umgebungsvariablen für alles, was sich zwischen Umgebungen ändert. Alle drei Formate können auf Anwendungsebene Umgebungsvariablen auslesen, sodass das Config-Format selbst keine Interpolation unterstützen muss.

Formatbeliebtheit nach Ökosystem

ÖkosystemPrimäres FormatBekannte Beispiele
JavaScript/Node.jsJSONpackage.json, tsconfig.json, .eslintrc.json
PythonTOMLpyproject.toml, Cargo.toml (Rust)
DevOps/CloudYAMLdocker-compose.yml, k8s Manifeste, GitHub Actions
GoTOML/YAMLBeide weit verbreitet, kein einzelner Standard
.NETJSONappsettings.json (hat XML-basierte web.config ersetzt)

Fazit

Es gibt keine einzelne richtige Antwort. Verwenden Sie JSON, wenn Sie maximale Kompatibilität brauchen. Verwenden Sie YAML, wenn das Ökosystem es verlangt (Kubernetes wird kein TOML akzeptieren). Verwenden Sie TOML, wenn Sie Kommentare und minimale Überraschungen wollen.

JSONC und JSON5: JSON mit Stützrädern

Okay, wir haben also JSON dafür kritisiert, keine Kommentare und Trailing-Kommas zu unterstützen. Aber hier ist die Sache, die Ihnen niemand erzählt: Es gibt tatsächlich JSON-Varianten, die diese Ärgernisse beheben, und Sie haben wahrscheinlich eine davon benutzt, ohne es zu merken.

Zuerst: JSONC (JSON with Comments). Wenn Sie jemals eine tsconfig.json geöffnet und gedacht haben „Moment, da sind Kommentare drin... ich dachte JSON erlaubt keine Kommentare?" — ja, das ist JSONC. Es ist im Grunde JSON, aber Sie können // Einzeilenkommentare und /* */ Blockkommentare verwenden. VS Code verwendet JSONC für seine settings.json, launch.json und keybindings.json Dateien. TypeScripts tsconfig.json ist technisch auch JSONC, nicht striktes JSON.

So sieht JSONC aus:

jsonc

Dann gibt es JSON5, das noch weiter geht. JSON5 lockert einige der strengsten JSON-Regeln:

  • Einfache Anführungszeichen für Strings: {'name': 'Sarah'} — endlich!
  • Trailing-Kommas: {"a": 1, "b": 2,} — kein Diff-Rauschen mehr
  • Schlüssel ohne Anführungszeichen (wenn sie gültige Bezeichner sind): {name: "Sarah"}
  • Hexadezimale Zahlen: 0xFF
  • Mehrzeilige Strings mit Backslash-Fortsetzung
  • Infinity, -Infinity und NaN als gültige Zahlen

JSON5 ist großartig für Config-Dateien, bei denen Menschen die Hauptzielgruppe sind. Einige Tools unterstützen es nativ — zum Beispiel kann Babels .babelrc JSON5 sein. Aber verwenden Sie JSON5 nicht für API-Responses oder Datenaustausch. Der ganze Sinn von striktem JSON ist, dass alle sich auf das Format einigen. JSON5 ist für Menschen, nicht für Maschinen.

Meine Faustregel: Wenn ein Tool JSONC oder JSON5 unterstützt, verwenden Sie es. Es gibt buchstäblich keinen Nachteil, Kommentare in Ihren Config-Dateien zu haben. Aber wenn Sie eine Bibliothek schreiben, die Config liest, unterstützen Sie zuerst Standard-JSON und JSONC/JSON5 als optionale Extras.

YAML Anker und Aliase: DRY Config

Hier kommt YAMLs echtes Killer-Feature, das viele Entwickler nie entdecken: Anker und Aliase. Sie ermöglichen es, einen Config-Block einmal zu definieren und überall wiederzuverwenden. Im Grunde DRY (Don't Repeat Yourself) für Config-Dateien.

Ein Anker wird mit &name markiert und ein Alias referenziert ihn mit *name. Hier ein praktisches Docker-Compose-Beispiel:

yaml

Sehen Sie, was passiert ist? Wir haben gemeinsame Einstellungen einmal mit &common definiert und sie mit <<: *common in drei Services eingefügt. Ohne Anker würden Sie diese Restart-Policy und Logging-Config in jeden einzelnen Service kopieren. Und wenn Sie die Log-Rotation ändern müssen? Eine Stelle statt zwölf.

Sie können Anker auch für einfachere Werte verwenden — nicht nur für Maps:

yaml

Nun die Stolperfallen. Der Merge-Schlüssel <<, der Anker so richtig mächtig macht? Er ist nicht wirklich Teil der YAML 1.2 Spezifikation. Es war eine YAML-1.1-Typerweiterung, und obwohl die meisten populären Parser ihn noch unterstützen, ist er technisch nicht standardisiert. Wenn Sie also einen strikten YAML 1.2 Parser verwenden, funktionieren Merge-Schlüssel möglicherweise nicht.

Außerdem funktionieren Anker nur innerhalb einer einzelnen Datei. Sie können keinen Anker referenzieren, der in einer anderen YAML-Datei definiert ist. Und die Fehlermeldungen, wenn Sie einen Aliasnamen falsch schreiben? Normalerweise sowas wie „undefined alias" ohne jeglichen Kontext darüber, wo der Anker hätte sein sollen. Typisch YAML.

TOML Vertiefung: Erweiterte Features

Die meisten kennen die TOML-Grundlagen — Abschnitte mit [Klammern], Schlüssel-Wert-Paare, Kommentare mit #. Aber TOML hat einige wirklich coole Features, die nicht genug Beachtung bekommen. Lassen Sie mich sie durchgehen.

Punktierte Schlüssel erlauben es, verschachtelte Strukturen ohne Abschnittsüberschriften zu definieren:

toml

Das ist praktisch, wenn Sie nur ein paar verschachtelte Werte haben und keinen ganzen Abschnitt dafür anlegen wollen.

Inline-Tabellen bieten eine JSON-ähnliche kompakte Syntax für kleine Objekte:

toml

Verwenden Sie Inline-Tabellen aber sparsam — sie können nicht über mehrere Zeilen gehen und werden schnell unleserlich, wenn Sie zu viel hineinstopfen.

Mehrzeilige Strings kommen in zwei Varianten, und hier wird TOML überraschend durchdacht:

toml

Der dreifach-gequotete einfache String (""") verarbeitet Escape-Sequenzen, während die literale Version (''') alles als Rohtext behandelt. Das ist perfekt für Regex-Muster oder Windows-Dateipfade, bei denen Backslashes nicht als Escapes interpretiert werden sollen.

Native Datum/Zeit-Typen sind etwas, das weder JSON noch YAML so sauber handhabt:

toml

Das sind erstklassige Typen in TOML, keine Strings, die so tun, als wären sie Daten. Ihr TOML-Parser gibt Ihnen echte Datum/Zeit-Objekte, keine Strings, die Sie selbst parsen müssen.

Warum hat Rusts Cargo TOML gewählt? Weil Cargo-Konfigurationen genau der Sweet Spot für TOML sind: moderat verschachtelt, von Menschen bearbeitet, braucht Kommentare und profitiert von strikter Typisierung. Sie wollen nicht, dass Ihre Abhängigkeitsversionen still als Floats interpretiert werden (ich schaue dich an, YAML).

Sicherheitsüberlegungen

Okay, das ist der Abschnitt, in dem es etwas beängstigend wird. Wenn Sie Config-Dateien aus nicht vertrauenswürdigen Quellen laden — oder auch wenn Sie denken, dass Sie es nicht tun — müssen Sie über Deserialisierungsangriffe Bescheid wissen.

Das Paradebeispiel dafür ist PyYAMLs yaml.load(). In älteren Versionen konnte diese unschuldig aussehende Funktion beliebigen Python-Code ausführen, der in einer YAML-Datei eingebettet war. Ich mache keine Witze. Schauen Sie sich das an:

yaml

Wenn jemand das in eine YAML-Config schmuggelt und Ihre Python-App es mit yaml.load() statt yaml.safe_load() lädt, wird es buchstäblich diesen Systembefehl ausführen. Alles löschen. Eine Hintertür installieren. Was immer der Angreifer will.

Die Lösung ist kinderleicht — verwenden Sie in Python immer yaml.safe_load():

python

Die PyYAML-Dokumentation warnt jetzt davor, und neuere Versionen zeigen eine Deprecation-Warnung, wenn Sie yaml.load() ohne Angabe eines Loaders verwenden. Aber es gibt immer noch unzählige Tutorials und Stack-Overflow-Antworten, die die unsichere Version zeigen. Es ist eine Landmine, die offen herumliegt.

Dann gibt es den „Billion Laughs"-Angriff (auch XML-Bombe genannt, aber funktioniert auch mit YAML). Die Idee ist rekursive Expansion — man definiert Entitäten, die andere Entitäten referenzieren und exponentielles Wachstum erzeugen:

yaml

Jede Ebene multipliziert die Daten mit 5, also blicken Sie bei Ebene 8 oder 9 auf Gigabytes an Daten aus ein paar Zeilen YAML. Die meisten modernen YAML-Parser haben Tiefen- und Expansionslimits, um das zu verhindern, aber es ist gut, davon zu wissen.

JSON ist von Natur aus sicherer, weil es keinerlei Ausführungssemantik hat. Es gibt keine Möglichkeit, Code einzubetten, keine Typkonstruktoren, keine Entity-Expansion. Ein JSON-Parser liest einfach Daten — Strings, Zahlen, Booleans, Arrays und Objekte. Das ist alles. Das ist einer der unterschätzten Vorteile der Einfachheit von JSON. Wenn Sicherheit wichtig ist, ist JSONs Mangel an Features tatsächlich ein Feature.

TOML ist ebenfalls recht sicher — es hat keine Code-Ausführungsfähigkeiten und keine rekursive Expansion. Aber es ist weniger kampferprobt als JSON-Parser, also halten Sie Ihre TOML-Bibliotheken auf dem neuesten Stand.

Fazit: Wenn Sie Config-Dateien von Benutzern oder externen Quellen akzeptieren, ist JSON die sicherste Wahl. Wenn Sie YAML verwenden müssen, benutzen Sie immer sichere Ladefunktionen und erwägen Sie, einen YAML-Linter einzusetzen, um verdächtige Konstrukte zu erkennen.

Praxisbeispiele für Config-Dateien

Theorie ist großartig, aber schauen wir uns echte Config-Dateien an, denen Sie in der Praxis begegnen werden. Ich habe jede annotiert, um formatspezifische Muster hervorzuheben.

GitHub Actions Workflow (YAML):

yaml

Hier glänzt YAML wirklich. Die GitHub Actions Workflow-Syntax wäre in JSON mühsam — all diese verschachtelten Listen und die einrückungsbasierte Struktur passt natürlich zu YAML. Sie können auch sehen, wie Kommentare die Matrix-Strategie erklären.

Rusts Cargo.toml (TOML):

toml

Beachten Sie, wie das Cargo-Manifest Inline-Tabellen für Abhängigkeiten mit Features verwendet. Die [[bin]] Doppelklammer-Syntax definiert ein Array von Tabellen — jeder [[bin]]-Eintrag fügt ein weiteres Binary-Target hinzu. TOML hält das flach und lesbar ohne Einrückungsspiele.

package.json (JSON):

json

Der Klassiker. Keine Kommentare, viele Anführungszeichen, aber jedes Tool auf dem Planeten kann es lesen. Was package.json trotz JSONs Einschränkungen funktionieren lässt, ist, dass das Schema so bekannt ist — Sie brauchen keine Kommentare, um zu erklären, was scripts.build tut, weil jeder JavaScript-Entwickler es bereits weiß.

.prettierrc (JSON):

json

Einfache, flache Schlüssel-Wert-Config. Ehrlich gesagt wäre das als TOML (Kommentare!) oder sogar JSONC etwas schöner, und Prettier unterstützt auch andere Formate. Aber JSON ist der Standard, und für etwas so Einfaches macht es kaum einen Unterschied.

Migration zwischen Formaten

Sie haben also entschieden, dass das Config-Format Ihres Projekts ein Fehler war und Sie wechseln wollen. Oder vielleicht ziehen Sie Config von einem Tool ein, das ein anderes Format verwendet. Wie auch immer, Sie müssen zwischen TOML, YAML und JSON konvertieren. Ich sage Ihnen, es läuft nicht immer so glatt, wie man hofft.

Tools für die Konvertierung:

  • yq — Das Schweizer Taschenmesser für YAML. Kann zwischen YAML, JSON, TOML und XML konvertieren. yq -o=json config.yaml gibt JSON aus. Es ist wie jq, aber für YAML.
  • toml-cli und taplo — Kommandozeilen-TOML-Prozessoren. Taplo ist besonders gut für TOML-Formatierung und -Validierung.
  • Python-Einzeiler — Im Notfall konvertiert python -c "import yaml, json, sys; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" < config.yaml YAML zu JSON. Nicht schön, aber funktioniert.
  • Online-Konverter — Für schnelle einmalige Konvertierungen können unsere Formatter helfen. Fügen Sie Ihre Config in den entsprechenden Formatter ein, bereinigen Sie sie und schreiben Sie sie manuell im Zielformat um.

Wann migrieren:

  • Ihr Team macht ständig YAML-Einrückungsfehler in CI-Configs? Vielleicht reduziert ein Wechsel zu TOML diese Kopfschmerzen.
  • Sie brauchen Kommentare in einer JSON-Config-Datei? Erwägen Sie die Migration zu JSONC (wenn das Tool es unterstützt) oder TOML.
  • Sie bauen ein neues Rust/Python-Projekt und das Ökosystem erwartet TOML? Kämpfen Sie nicht dagegen an — nehmen Sie TOML.

Häufige Stolperfallen bei der Migration:

YAMLs implizites Datums-Parsing wird Sie erwischen. Wenn Sie einen YAML-Wert wie release: 2024-03-08 haben, interpretiert YAML das als Datumsobjekt, nicht als String. Konvertieren Sie das zu JSON und Sie bekommen möglicherweise "release": "2024-03-08T00:00:00Z" oder "release": "2024-03-08", je nach Konverter. Testen Sie immer Ihre Ausgabe.

TOMLs strikte Typisierung bedeutet, dass Sie keine gemischten Arrays haben können. In JSON und YAML ist [1, "two", true] völlig in Ordnung. In TOML muss jedes Element in einem Array denselben Typ haben. Wenn Ihre Quelldaten gemischte Arrays haben, müssen Sie umstrukturieren.

Und hier ist der große Punkt: Kommentare gehen verloren. JSON unterstützt keine Kommentare, also verschwinden all Ihre sorgfältig geschriebenen Kommentare, wenn Sie von TOML oder YAML zu JSON konvertieren. In die andere Richtung (JSON zu YAML/TOML) werden Sie manuell Kommentare hinzufügen wollen, um nicht-offensichtliche Einstellungen zu erklären, weil die JSON-Version sie sicher nicht hatte.

Noch etwas — YAMLs Anker und Aliase haben keine Entsprechungen in JSON oder TOML. Wenn Ihre YAML-Config auf Anker für DRY-Config angewiesen ist, bedeutet die Konvertierung in ein anderes Format, dass Sie diese gemeinsamen Blöcke manuell duplizieren müssen. Das kann bei komplexen Configs eine erhebliche Größenzunahme bedeuten.

Probieren Sie es selbst aus

Welches Format Sie auch wählen, gut formatierte Configs sind leichter zu überprüfen und zu debuggen. Unser TOML Formatter räumt unordentliche TOML-Dateien sofort auf. Der YAML Formatter behebt Einrückungsprobleme, bevor sie Probleme verursachen. Und der JSON Formatter macht selbst tief verschachtelte JSON-Configs auf einen Blick lesbar.