Comparison8 min read

YAML vs JSON vs TOML: Which Config Format Should You Use?

JSON, YAML, and TOML each optimize for a different reader. Learn the trade-offs, where each one bites you in production, and how to choose for a new project.

YAML, JSON, and TOML are the three formats you'll meet writing config files in 2025. They all encode the same kind of data — strings, numbers, lists, nested maps — but each one optimizes for a different reader. Pick the wrong one and your config becomes hard to read, hard to validate, or quietly buggy. Here's the practical comparison.

At a Glance

The same configuration in all three:

JSON:

{
  "name": "my-app",
  "version": "1.0.0",
  "dependencies": ["react", "next"],
  "server": {
    "host": "localhost",
    "port": 3000
  }
}

YAML:

name: my-app
version: 1.0.0
dependencies:
  - react
  - next
server:
  host: localhost
  port: 3000

TOML:

name = "my-app"
version = "1.0.0"
dependencies = ["react", "next"]

[server]
host = "localhost"
port = 3000

Same data, three philosophies.

What Each Format Optimizes For

JSON: machine-to-machine. Strict syntax, easy to parse, no ambiguity. Designed as a JavaScript-friendly subset for APIs.

YAML: human writers. Indentation-based, no quotes for simple strings, supports comments. Designed to be edited by hand.

TOML: config files specifically. Section headers, no significant whitespace, unambiguous types. Designed to be obvious to read and impossible to mis-indent.

Side-by-Side Comparison

Feature JSON YAML TOML
Comments No Yes (#) Yes (#)
Indentation matters No Yes (significant) No
Trailing commas No N/A Yes
Multiline strings No (escape \n) Yes (|, >) Yes (""")
Type inference Explicit Implicit (gotchas) Explicit
Date/time literals No Yes Yes
Schema validation JSON Schema (mature) JSON Schema (works) Less mature
Parser size/speed Tiny, fast Big, slower Small, fast
Specification length Short Long, complex Short
Best for APIs, data interchange Configs, k8s, CI Single-file configs

When YAML Bites You

YAML is the most "user-friendly" until it's not. The Norway Problem is the canonical example:

countries:
  - NO    # YAML parses this as the boolean `false`
  - SE
  - FI

YAML 1.1 interprets NO, YES, ON, OFF as booleans. So a list of country codes silently becomes [false, "SE", "FI"]. YAML 1.2 fixes this by only treating true/false as booleans — but most parsers still default to YAML 1.1 behavior.

Other YAML pitfalls:

  • Indentation sensitivity. A single misplaced space changes the parse result. key: value and key:\n value are different.
  • Implicit typing. version: 1.10 becomes the float 1.1. To preserve "1.10", you have to quote it.
  • Anchors and aliases (&, *). Powerful but obscure. Most users never learn them.
  • Multiple documents per file. YAML supports --- separators between documents. Most parsers handle the first one and silently drop the rest.

If you need YAML, use a parser that targets YAML 1.2 (sometimes called "Core" schema) and prefer to quote values that look like booleans, numbers, or dates.

When JSON Bites You

JSON is strict and unforgiving:

  • No comments — so JSON config files end up with _comment fields or live alongside a documentation file.
  • No trailing commas — common copy-paste error that breaks the file.
  • All keys are quoted — verbose for hand-written config.
  • No multi-line strings — escape \n everywhere.

These are the reasons JSONC (JSON with Comments, used by VS Code) and JSON5 (relaxed JSON) exist. They patch JSON's UX gaps but aren't supported by JSON.parse() and don't have the same ecosystem of validators.

When TOML Shines

TOML's trick is that section headers ([server]) make the structure obvious without indentation:

[server]
host = "localhost"
port = 3000

[server.tls]
cert = "cert.pem"
key = "key.pem"

You can see the nesting, but you can't accidentally break it with a wrong-width tab. Combined with explicit typing — strings are quoted, numbers aren't, dates have a literal 1979-05-27T07:32:00Z syntax — TOML is unusually hard to mis-write.

TOML's weakness is deeply nested or array-heavy data. Once you have arrays of objects, TOML's [[array_of_tables]] syntax gets noisy:

[[users]]
name = "Alice"
age = 30

[[users]]
name = "Bob"
age = 25

For that shape, JSON or YAML stays cleaner.

Where You'll See Each in the Wild

JSON is the dominant config format for:

  • package.json (npm)
  • tsconfig.json (TypeScript)
  • composer.json (PHP)
  • API request/response bodies
  • VS Code settings.json

YAML is dominant for:

  • Kubernetes manifests
  • GitHub Actions, GitLab CI, CircleCI workflows
  • Ansible playbooks
  • Docker Compose
  • OpenAPI / Swagger specs

TOML is dominant for:

  • Rust's Cargo.toml
  • Python's pyproject.toml (PEP 518)
  • Hugo, Zola static site generators
  • .github/dependabot.yml is YAML, but Dependabot itself reads pyproject.toml

When choosing for a new project, follow the convention of your ecosystem. A new Rust crate uses TOML. A new Kubernetes operator uses YAML. A new TypeScript library uses JSON.

How to Format and Validate Online

Use DevZone's YAML Formatter to validate and pretty-print YAML, with explicit error messages for indentation and type issues. The same approach works for JSON via the JSON Formatter.

For each format:

  1. Paste your config.
  2. The tool validates the syntax — if it's invalid, the line and reason are shown.
  3. The output is the canonical, indented version.

Both tools run in the browser; nothing is uploaded.

Choosing for a New Project

A short decision tree:

  • Talking to an API? → JSON. Always.
  • Single-file project config (Rust, Python, static site)? → TOML.
  • Config that needs comments, multiline strings, or anchors? → YAML, but lock the parser to YAML 1.2.
  • Config that you generate from code? → JSON. Easy to emit, validates with JSON Schema.
  • Config edited by non-developers? → TOML or YAML, with examples in the comments.

If you're hesitating between YAML and TOML, the deciding question is usually "how nested is this data?" Shallow data is more readable in TOML. Deeply nested data is more readable in YAML.

FAQ

Can YAML be used as a JSON superset?

Yes — YAML 1.2 is technically a superset of JSON. Any valid JSON is valid YAML. This means a YAML parser will happily eat a package.json. The reverse is not true.

Why does Kubernetes use YAML and not TOML?

History. Kubernetes inherited YAML from Docker Compose and the broader DevOps ecosystem in 2014. By the time TOML stabilized, the convention was set. There have been periodic suggestions to support alternative formats; none have shipped.

Is JSON5 a real standard?

JSON5 has a published spec but isn't supported by built-in parsers (JSON.parse). You need an external library. It's mostly a developer convenience for hand-edited config; for data interchange, use real JSON.

What about INI files?

INI is the older, looser ancestor of TOML. Same [section] syntax, but no formal spec, no nested sections, and inconsistent type handling between parsers. Use TOML for new code; treat INI as a legacy format.

Which format has the best tooling?

JSON, by a wide margin. JSON Schema validation, IDE autocomplete from schemas, jq for querying, and instantly parseable in every language. YAML's tooling is good but the spec ambiguities cause more bugs. TOML's tooling is improving but still smaller.

Try the tools