Keine Werbung mögen? Gehen Werbefrei Heute

YAML gegen JSON gegen TOML — Welche Konfigurationsform sollte man tatsächlich verwenden?

Aktualisiert am

YAML, JSON und TOML speichern alle Konfigurationen. Sie sind nicht austauschbar. YAML wandelt Ihre Ländercode schweigend in einen Boolean um. JSON lässt keine Kommentare zu. TOML ist die Sprache, die keiner auf deinem Team bisher verwendet hat. Hier ist, wie man die richtige wählt.

YAML vs JSON vs TOML – Welche Konfigurationsform sollte man tatsächlich verwenden? 1
ANZEIGE Entfernen?

Im Jahr 2015 brach ein Ansible-Playbook wegen dieser Zeile:

country: NO

Die Konfiguration wurde ohne Fehler geladen. Keine Parser-Kritik. Doch country war nicht auf den String "NO"festgelegt. falsewar festgelegt. NO Weil in YAML 1.1 yes, on, off, yund nein Boolescher Wert ist. Ebenso ist

Das ist das Problem von Norwegen, und es hat sich seit Jahren schweigend auf Konfigurationen ausgewirkt.

Dies ist kein YAML-Bugbericht. Es ist eine Rahmenbedingung für die Entscheidung, die Sie kurz vorher treffen werden: YAML, JSON oder TOML für Ihre nächste Konfigurationsdatei? Jede dieser Formate hat echte Abwägungen, und die Antwort „Verwenden Sie einfach das, was die Ecosystem verwendet“ gilt nicht immer.

Die Gleiche Konfiguration, in drei Formaten

YAML

# App configuration
app:
  name: my-api
  port: 8080
  debug: false

database:
  host: localhost
  port: 5432
  name: mydb
  pool_size: 10

logging:
  level: info
  format: json
  outputs:
    - stdout
    - /var/log/app.log

JSON

{
  "app": {
    "name": "my-api",
    "port": 8080,
    "debug": false
  },
  "database": {
    "host": "localhost",
    "port": 5432,
    "name": "mydb",
    "pool_size": 10
  },
  "logging": {
    "level": "info",
    "format": "json",
    "outputs": [
      "stdout",
      "/var/log/app.log"
    ]
  }
}

TOML

# App configuration
[app]
name = "my-api"
port = 8080
debug = false

[database]
host = "localhost"
port = 5432
name = "mydb"
pool_size = 10

[logging]
level = "info"
format = "json"
outputs = ["stdout", "/var/log/app.log"]

Bevor der Zusammenbruch eintrat, ist hier die gleiche App-Konfiguration in allen drei Formaten geschrieben:

YAML ist kompakter, aber syntaktisch belastend. JSON ist umfangreicher, aber explizit. TOML liegt dazwischen: lesbar ohne die impliziten Typumwandlungen von YAML.

YAML ist die Standardwahl für CI/CD-Pipelines (GitHub Actions, GitLab CI, CircleCI), Kubernetes-Manifeste, Ansible-Playbooks und die meisten Entwicklertools. Sie entscheiden nicht wirklich für YAML – es wählt Sie.

Die Fallen, dokumentiert:

1. Das Problem der Booleschen Werte (Das Problem von Norwegen)

YAML 1.1 – die Spezifikation, die die meisten Parser tatsächlich implementieren – behandelt eine bemerkenswert große Anzahl von Strings als Boolesche Werte:

# YAML 1.1 boolean values (all parsed as true or false)
enabled: yes      # true
disabled: no      # false  
active: on        # true
paused: off       # false
valid: true       # true
invalid: false    # false

# The Norway Problem in practice:
country_codes:
  NO: Norway      # Key "NO" is fine, but value "NO" becomes false
  SE: Sweden
  YES: Yemen      # "YES" also becomes true

# The fix: quote your strings
country_codes:
  NO: "Norway"
  SE: "Sweden"

YAML 1.2 (2009 veröffentlicht) hat dies behoben – nur true und false sind Boolesche Werte. Das Problem ist, dass PyYAML nicht vollständig die 1.2-Verhalten bis zur Version 6.0 im Jahr 2021 übernahm, und Go’s beliebter gopkg.in/yaml.v2 verwendet bis heute 1.1-Semantik im Jahr 2024. Wenn Sie Ruby’s Psych unter 4.0 oder jedes vor-6.0-PyYAML verwenden, sind Sie auf 1.1.

2. Tabs töten Ihre Konfiguration

YAML verbietet Tab-Zeichen für Einrückung. Nur Leerzeichen sind gültig. Ihr Editor könnte Tabs und Leerzeichen gleich aussehen, die Datei könnte korrekt aussehen, und YAML wirft dennoch:

yaml.scanner.ScannerError: while scanning a block mapping
  found character '\t' that cannot start any token

Dies ist der Fehler, der junioren Entwicklern ihre Karrierefragen stellt. Stellen Sie Ihren Editor so ein, dass Tabs in YAML-Dateien in Leerzeichen umgewandelt werden. Jeder Editor unterstützt dies; nicht jeder hat es standardmäßig aktiviert.

3. Mehrzeilige Strings sind nicht offensichtlich

# | (literal block): preserves newlines exactly
description: |
  Line one.
  Line two.
  Line three.
# Result: "Line one.\nLine two.\nLine three.\n"

# > (folded block): folds newlines into spaces
short_desc: >
  This will all become
  one long line.
# Result: "This will all become one long line.\n"

# Trailing newlines: | adds one, |+ adds all, |- strips them all
desc_stripped: |-
  No trailing newline.

Niemand merkt das ohne nachzuschauen. Der Mnemotechnik, die ich verwende: | sieht wie eine Zeilenumbruch aus, > sieht wie etwas, das zusammengedrückt wird. Es ist immer noch drei Jahre später verwirrend.

Wenn YAML gewinnt

  • Sie schreiben Kubernetes-Manifeste, GitHub Actions-Workflows oder Ansible-Playbooks – Sie haben keine Wahl.
  • Ihre Konfiguration enthält viele Kommentare, die nicht offensichtliche Werte erklären. YAML unterstützt Inline-Comment. JSON und TOML unterstützen das ebenfalls, aber YAML fühlt sich für annotierungsreiche Konfigurationen am natürlichsten an.
  • Ihre Daten haben tief verankerte Strukturen, die mit TOMLs flachen Tabellen schrecklich aussehen würden.
  • Das Team ist bereits fließend und hat ein Linter (yamllint) im Pipeline.

JSON: Das langwehme, zuverlässige Werkzeug

JSON wurde als Datenaustauschformat konzipiert, nicht als Konfigurationsformat. Douglas Crockford hat absichtlich Kommentare ausgelassen – seine Argumentation war, dass Kommentare für Direktiven verwendet würden, die die Parser unterscheiden würden. Deswegen package.json hat keine Kommentare und tsconfig.json ist technisch JSON mit Kommentaren (JSONC), was eine separate Sache ist, die die meisten JSON-Parsers nicht unterstützen.

Die echten Probleme von JSON für Konfigurationsdateien:

  • Keine Kommentare. Sie können nicht erklären, warum "maxRetries": 3 und nicht 5. Sie können keine TODO-Notiz hinterlassen. Sie können ein Feld nicht als veraltet markieren. Das ist wirklich schmerzhaft für Konfigurationsdateien, die ihre Autoren übersteigen.
  • Keine Endkommas. Wenn Sie ein Element zu einem Array hinzufügen, müssen Sie die vorherige Zeile ändern, um ein Komma hinzuzufügen. Jede JSON-Änderung wird zu einer 2-Zeilen-Änderung. Jeder Merge-Konflikt wird etwas schlimmer als nötig.
  • Umständlich für verschachtelte Daten. Sechs Zeilen Klammern und Klammern für was YAML in drei Zeilen Einrückung macht.
  • Alle Zahlen sind derselbe Typ. JSON unterscheidet nicht zwischen ganzen Zahlen und Gleitkommazahlen. 1 und 1.0 sind beide nur Zahlen, und was Ihre Sprache bei der Deserialisierung daraus wählt, hängt vom Parser ab.

Aber die Vorhersagbarkeit von JSON ist auch seine Hauptmerkmale. Jede Sprache hat einen JSON-Parser. Die Spezifikation ist unmissverständlich. Es gibt keine impliziten Typumwandlungen. Ein String ist immer ein String – "yes" wird niemals schweigend zu trueumgewandelt. Wenn Sie eine JSON-Konfiguration programmatisch validieren müssen, IO Tools’ JSON Formatter kann Syntaxfehler vor der Produktion erkennen – nützlich, wenn jemand eine Konfiguration manuell bearbeitet und ein Endkomma vergisst.

Wenn JSON gewinnt

  • API-Antworten oder Konfigurationen, die von mehreren Sprachen/Services konsumiert werden. JSON ist universell; TOML-Unterstützung ist in einigen Ecosystems unvollständig.
  • Sie benötigen strenge Typgarantien. JSON-Schema-Validierung ist reif, gut unterstützt und weit verbreitet (VS Code verwendet es für Einstellungs-Vorschläge).
  • Die Konfiguration wird maschinell generiert. Niemand schreibt JSON manuell, wenn er es vermeiden kann – aber Maschinen generieren es problemlos.
  • Sie arbeiten in Node.js oder Frontend-JavaScript, wo JSON ein natives Mitglied ist.

TOML: Eine opinions-based Konfiguration, richtig gemacht

TOML (Tom’s Obvious, Minimal Language) wurde von Tom Preston-Werner, dem Mitgründer von GitHub, speziell für Konfigurationsdateien entwickelt. Es erreichte Version 1.0 im Januar 2021. Es ist das Standardformat für Rusts Cargo.toml, Pythons pyproject.tomlund Hugo-Statikseiten.

Das Design-Prinzip von TOML: Typen sollten explizit sein, Strukturen sollten so flach wie möglich sein und es sollte genau eine offensichtliche Methode geben, um jeden Konfigurationswert zu schreiben.

# Types are unambiguous in TOML
name = "my-app"          # string: always quoted
port = 8080              # integer
threshold = 3.14         # float
enabled = true           # boolean: only true/false, no yes/no
created = 2024-01-15     # date: native type
tags = ["api", "prod"]   # array

# "yes" is just a string. Always.
country = "NO"           # string "NO", no boolean nonsense

Die unvollkommenen Kanten:

  • Arrays von Tabellen-Syntax sind wirklich unangenehm. [[products]] und [products.details] sehen ähnlich aus, aber verhalten sich völlig unterschiedlich. Die Spezifikation macht Sinn; die visuelle Unterscheidung nicht.
  • Tiefes Verschachteln wird umständlich. Was YAML in 5 eingerückten Zeilen macht, macht TOML in 3 separaten Abschnittsüberschriften. Für Konfigurationen über 3 Ebenen tief, beginnt TOML, sich als falsches Werk zu empfinden.
  • Verfügbarkeit von Parsers. TOML-Parsers existieren für jede wichtige Sprache, aber sie variieren in Spezifikationskonformität. Das TOML-Konformitäts-Testset entdeckt regelmäßig Randfälle. JSON-Parsers wurden um ein Vielfaches mehr verwendet und getestet.
  • Teamvertrautheit. Wenn Sie TOML außerhalb des Rust- oder Python-Ecosystems verwenden, erwarten Sie mindestens einen Teammitglied, der einen PR mit „Was ist dieses Format?“ öffnet.

Wenn TOML gewinnt

  • Rust-Projekte – Cargo.toml ist die Standard und die Tooling ist hervorragend.
  • Python-Projekte, die pyproject.toml (PEP 518) – dies ist jetzt das empfohlene Heim für Werkzeugkonfigurationen wie Black, Ruff, mypy und pytest.
  • Einfache, flache Konfigurationen, bei denen die Einrückungsempfindlichkeit von YAML eine Belastung wäre.
  • Sie wollen native Datum-/Zeitunterstützung ohne Seriellierung zu Strings.

Die schnelle Entscheidungsleitfaden

  • Kubernetes / CI/CD-Pipeline / Ansible? YAML. Keine Wahl.
  • API-Konfiguration, die von mehreren Diensten in verschiedenen Sprachen konsumiert wird? JSON.
  • Rust-Projekt? TOML (Cargo.toml-Standard).
  • Python-Projekt-Konfiguration (Linter, Formatter, Build-Tools)? TOML (pyproject.toml ist jetzt der Standard).
  • Statikseite-Konfiguration (Hugo, Zola)? TOML, obwohl diese normalerweise alle drei unterstützen.
  • Node.js-Projekt-Konfiguration? JSON (package.json-Ecosystem), oder YAML, wenn Kommentare benötigt werden.
  • Menschen bearbeiten diese häufig und benötigen Notizen? YAML oder TOML (beide unterstützen Kommentare). Nicht JSON.
  • Sie wollen strenge Typsicherheit und Schema-Validierung? JSON + JSON-Schema.

Die ehrliche Antwort für die meisten neuen Projekte: Verwenden Sie das, was das Haupt-Ökosystem der Sprache erwartet. Rust erwartet TOML. Python-Tools erwartet TOML oder YAML. Node.js erwartet JSON. Wenn Sie etwas sprachunabhängig schreiben, ist eine vernünftige Standardteilung: TOML für menschlich bearbeitete Konfigurationen und JSON für maschinell generierte/verbrauchte Konfigurationen.

Möchten Sie werbefrei genießen? Werde noch heute werbefrei

Erweiterungen installieren

IO-Tools zu Ihrem Lieblingsbrowser hinzufügen für sofortigen Zugriff und schnellere Suche

Zu Chrome-Erweiterung Zu Kantenerweiterung Zu Firefox-Erweiterung Zu Opera-Erweiterung

Die Anzeigetafel ist eingetroffen!

Anzeigetafel ist eine unterhaltsame Möglichkeit, Ihre Spiele zu verfolgen. Alle Daten werden in Ihrem Browser gespeichert. Weitere Funktionen folgen in Kürze!

ANZEIGE Entfernen?
ANZEIGE Entfernen?
ANZEIGE Entfernen?

Nachrichtenecke mit technischen Highlights

Beteiligen Sie sich

Helfen Sie uns, weiterhin wertvolle kostenlose Tools bereitzustellen

Kauf mir einen Kaffee
ANZEIGE Entfernen?