ToolSite
All posts

TOML vs YAML vs JSON: Choosing a Config Format

TOML, YAML, or JSON? Compare syntax, comments, readability, and ecosystem support. Pick the right config format for your project with our free converters.

By ToolSite5 min readguides

Three Formats, Different Philosophies

JSON, YAML, and TOML all represent structured data as plain text. They overlap heavily in what they can express, but they differ in who they're designed for.

  • JSON was designed for data interchange between machines.
  • YAML was designed for human-written configuration files.
  • TOML was designed specifically for configuration and aims to be simpler and safer than YAML.

Choosing the right one depends on who writes the file, who reads it, and how deeply nested the data gets.

TOML

TOML (Tom's Obvious, Minimal Language) looks like INI files with a type system. It uses [sections] for grouping, key = value pairs for data, and supports arrays, inline tables, and dates natively.

[server]
host = "0.0.0.0"
port = 8080
tls = true

[database]
engine = "postgresql"
pool_size = 10

[[users]]
name = "Alice"
role = "admin"

[[users]]
name = "Bob"
role = "user"

TOML's design goals are explicit: map unambiguously to a hash table, be easy to parse, and be minimal. It has comments (#), and its syntax is flat enough that indentation errors, YAML's biggest weakness, don't exist. TOML also has native date and time types, which neither JSON nor YAML handle as cleanly.

TOML is the default config format for Rust projects (Cargo.toml), Python packaging (pyproject.toml), and is gaining traction in the Go ecosystem. Tools like ripgrep and bat use TOML for their config files.

JSON

JSON needs little introduction. It's the lingua franca of web APIs:

{
  "server": {
    "host": "0.0.0.0",
    "port": 8080,
    "tls": true
  }
}

JSON's strength is its universality. Every language parses it the same way. Schema validation (JSON Schema) is mature and widely supported. But JSON has no comments, requires double quotes on every string and key, and forbids trailing commas. For hand-written config, these are friction points. For machine-generated config, they are non-issues.

YAML

YAML prioritizes human readability above all else:

server:
  host: 0.0.0.0
  port: 8080
  tls: true

Comments, minimal punctuation, and visual nesting make YAML the default choice for Kubernetes, Docker Compose, Ansible, and CI/CD pipelines. Anchors and aliases reduce repetition in large files.

The tradeoff is safety. YAML's type coercion turns yes into true, NO into false, and 012 into 10. Indentation errors silently change structure. For teams that use YAML heavily, a linter and a validator are essential tools.

Comparison Table

JSONYAMLTOML
CommentsNoYes (#)Yes (#)
WhitespaceIgnoredSignificantIgnored
Multi-line stringsNoYesYes (""")
DatesNo (string only)Yes (tagged)Yes (native)
Anchors/aliasesNoYesNo
Deep nestingNaturalNaturalAwkward
Type coercion trapsNoneManyMinimal
Parser complexityMinimalVery highModerate
Standard libraryEvery languagePython (PyYAML), others varyRust, Python 3.11+, growing

Where Each Shines

JSON wins when:

  • Data flows between systems (APIs, message queues, browser storage)
  • Config is generated by a tool, not handwritten
  • You need guaranteed, identical parsing across every language
  • You want schema validation for your config files
  • You're building a public API and need the widest possible client support

YAML wins when:

  • Config files are large and hand-maintained
  • You need comments to explain why values are set a certain way
  • You're in a DevOps ecosystem (Kubernetes, Ansible, Docker Compose, CI/CD)
  • You need anchors and aliases to avoid repeating shared values
  • Your tooling already expects YAML and provides schema-aware editing

TOML wins when:

  • You want the readability of YAML without the indentation traps
  • Your config has a shallow, table-like structure
  • You're building a tool and want the simplest possible config format for your users (Rust's Cargo.toml, Python's pyproject.toml)
  • You want dates and times as first-class types
  • You want minimal parser complexity and near-zero type coercion surprises

Why Not TOML Everywhere?

TOML handles deeply nested structures poorly. A YAML document like:

server:
  routes:
    api:
      v1:
        endpoint: /api/v1

In TOML, deep nesting creates long, repetitive section headers:

[server.routes.api.v1]
endpoint = "/api/v1"

For configurations with more than two or three levels of nesting, YAML or JSON are more ergonomic. TOML is best when your config is mostly flat with one or two levels of grouping. This covers a large fraction of real-world config files: package manifests, tool settings, and build configurations rarely need deep nesting.

The Migration Path

If you're starting a new project, pick TOML for simple config, YAML for complex, hand-maintained config, and JSON for API payloads and machine-generated config.

If you have an existing JSON config and want comments, convert to YAML. If you have a YAML config and are tired of indentation bugs, convert to TOML. The TOML to JSON Converter and YAML to JSON Converter let you test drive formats before committing to one. Convert a representative config file to each format and see which one reads best to you and your team.

Try it yourself: open the TOML to JSON Converter and paste a TOML snippet. Convert it to JSON and observe the structural differences: TOML's [sections] become nested JSON objects. Then open the YAML to JSON Converter and compare how the same data looks in each format. Try a config with a few levels of nesting and see where each format starts to feel awkward.

Related Reading