DevToolBoxFREE
Blog

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

10 min readby DevToolBox

JSON, YAML, and TOML are the three most popular configuration formats in software development. Each has distinct strengths and trade-offs. This guide provides a comprehensive comparison to help you choose the right format for your project.

Convert between JSON and YAML instantly with our free tool β†’

Overview of Each Format

JSON (JavaScript Object Notation)

JSON was introduced in the early 2000s by Douglas Crockford as a lightweight data-interchange format derived from JavaScript object literal syntax. Its design goal was simplicity: a minimal set of rules that any programming language could parse easily. Today it is the de facto standard for web APIs, configuration files like package.json and tsconfig.json, and data storage.

YAML (YAML Ain't Markup Language)

YAML was first proposed in 2001 by Clark Evans, Ingy dΓΆt Net, and Oren Ben-Kiki. Originally meaning "Yet Another Markup Language," it was later renamed to reflect its data-oriented (not document-oriented) nature. YAML was designed for human readability and is widely used in DevOps tools like Docker Compose, Kubernetes manifests, Ansible playbooks, and CI/CD configurations (GitHub Actions, GitLab CI).

TOML (Tom's Obvious Minimal Language)

TOML was created in 2013 by Tom Preston-Werner (co-founder of GitHub) specifically to be a minimal and unambiguous configuration format. It aims to be easy to read due to obvious semantics, mapping cleanly to a hash table. TOML is the standard config format for Rust (Cargo.toml), Python (pyproject.toml), and Hugo static sites.

Syntax Comparison

Here is the same configuration expressed in all three formats:

JSON

{
  "server": {
    "host": "localhost",
    "port": 8080,
    "debug": true
  },
  "database": {
    "host": "db.example.com",
    "port": 5432,
    "name": "myapp",
    "credentials": {
      "username": "admin",
      "password": "secret"
    }
  },
  "features": ["auth", "logging", "cache"],
  "max_connections": 100
}

YAML

# Server configuration
server:
  host: localhost
  port: 8080
  debug: true

# Database settings
database:
  host: db.example.com
  port: 5432
  name: myapp
  credentials:
    username: admin
    password: secret

features:
  - auth
  - logging
  - cache

max_connections: 100

TOML

# Server configuration
max_connections = 100
features = ["auth", "logging", "cache"]

[server]
host = "localhost"
port = 8080
debug = true

[database]
host = "db.example.com"
port = 5432
name = "myapp"

[database.credentials]
username = "admin"
password = "secret"

Feature Comparison

FeatureJSONYAMLTOML
CommentsNoYes (#)Yes (#)
Data Typesstring, number, boolean, null, array, objectstring, int, float, bool, null, date, array, map + custom tagsstring, integer, float, boolean, datetime, array, table
ReadabilityMedium β€” braces and quotes add noiseHigh β€” clean indentation-based syntaxHigh β€” INI-like, explicit sections
StrictnessVery strict β€” no trailing commas, no commentsLoose β€” implicit typing causes surprisesStrict β€” explicit types, minimal ambiguity
Tooling SupportExcellent β€” universal parser supportGood β€” parsers in all major languagesGood β€” growing, strong in Rust/Python/Go
Multi-line StringsNo (use \n escape sequences)Yes (| for literal, > for folded)Yes (triple-quoted strings)

When to Use Each Format

Use JSON When...

  • Building or consuming REST APIs β€” JSON is the universal API payload format
  • Working with package.json, tsconfig.json, or composer.json
  • Storing data that machines read more than humans (logs, exports)
  • You need the widest possible tooling and parser support
  • Data interchange between different programming languages
// Typical JSON use cases
// package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "dev": "next dev",
    "build": "next build"
  }
}

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true
  }
}

Use YAML When...

  • Writing Docker Compose files or Kubernetes manifests
  • Configuring CI/CD pipelines (GitHub Actions, GitLab CI, CircleCI)
  • Using Ansible playbooks or Helm charts
  • You need comments in your configuration
  • Human readability is the top priority and indentation discipline is maintained
# Docker Compose
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html

# GitHub Actions
name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

Use TOML When...

  • Configuring Rust projects (Cargo.toml)
  • Setting up Python projects (pyproject.toml, Poetry, Black, Ruff)
  • Configuring Hugo static site generator
  • You want an unambiguous format with no implicit type coercion
  • Your config has clear sections/groups (TOML tables map well to this)
# Cargo.toml (Rust)
[package]
name = "my-app"
version = "0.1.0"
edition = "2021"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

# pyproject.toml (Python)
[project]
name = "my-package"
version = "1.0.0"
requires-python = ">=3.9"

[tool.ruff]
line-length = 88
target-version = "py39"

Common Pitfalls

YAML: Indentation Issues

YAML uses indentation to define structure. Mixing tabs and spaces, or using inconsistent indent levels, is the most common source of YAML errors.

# BAD: mixing tabs and spaces (invisible but breaks YAML)
services:
	web:          # tab character - YAML error!
    image: nginx

# BAD: inconsistent indentation
services:
  web:
      image: nginx   # 4 spaces here
    ports:            # 2 spaces here - error!
      - "80:80"

# GOOD: consistent 2-space indentation
services:
  web:
    image: nginx
    ports:
      - "80:80"

YAML: The "Norway Problem"

In YAML 1.1, unquoted values like NO, yes, on, off are interpreted as booleans. The country code "NO" (Norway) becomes false. This has caused real-world bugs. YAML 1.2 fixed this, but many parsers still default to 1.1 behavior.

# The "Norway Problem" - YAML 1.1
countries:
  - name: Norway
    code: NO          # Parsed as boolean false!
  - name: Sweden
    code: SE          # Parsed as string "SE"
  - name: Finland
    code: FI          # Parsed as string "FI"

# Other surprising boolean values in YAML 1.1:
truthy:  yes          # boolean true
falsy:   no           # boolean false
enabled: on           # boolean true
disabled: off         # boolean false
positive: TRUE        # boolean true
negative: False       # boolean false

# FIX: Always quote values that could be misinterpreted
countries:
  - name: Norway
    code: "NO"        # Now correctly a string
  - name: Sweden
    code: "SE"
settings:
  enabled: "yes"      # Now correctly a string

JSON: Trailing Commas

JSON does not allow trailing commas. Adding a comma after the last element in an array or object causes a parse error. This is a frequent mistake when manually editing JSON files.

// BAD: trailing comma after last element
{
  "name": "my-app",
  "version": "1.0.0",
  "private": true,    // <-- trailing comma = PARSE ERROR
}

// BAD: trailing comma in array
{
  "colors": [
    "red",
    "green",
    "blue",            // <-- trailing comma = PARSE ERROR
  ]
}

// GOOD: no trailing commas
{
  "name": "my-app",
  "version": "1.0.0",
  "private": true
}

TOML: Nested Table Syntax

Deeply nested structures in TOML can become verbose. Each level requires its own [section.subsection] header, which can be less intuitive than JSON or YAML nesting for complex hierarchies.

# TOML: deeply nested config can be verbose
[server]
host = "localhost"

[server.ssl]
enabled = true

[server.ssl.certificates]
cert = "/path/to/cert.pem"
key = "/path/to/key.pem"

[server.ssl.certificates.ca]
bundle = "/path/to/ca-bundle.pem"

# The same in YAML is more compact:
# server:
#   host: localhost
#   ssl:
#     enabled: true
#     certificates:
#       cert: /path/to/cert.pem
#       key: /path/to/key.pem
#       ca:
#         bundle: /path/to/ca-bundle.pem

# TOML inline tables can help for shallow nesting:
[server]
host = "localhost"
ssl = { enabled = true, cert = "/path/to/cert.pem" }

Conversion Tools

Need to switch between formats? Use our free online converters:

JSON ↔ YAML Converter β€” bidirectional conversion with formatting options

TOML ↔ YAML Converter β€” convert between TOML and YAML instantly

Frequently Asked Questions

Which is faster to parse: JSON, YAML, or TOML?

JSON is generally the fastest to parse because of its simple, strict grammar. Most JSON parsers are highly optimized and available as native implementations. TOML is also fast due to its unambiguous syntax. YAML is typically the slowest to parse because of its complex specification with features like anchors, custom tags, and implicit typing.

Can I use comments in JSON?

Standard JSON (RFC 8259) does not support comments. Some tools like JSON5 and JSONC (used in VS Code settings) extend JSON with comment support, but these are non-standard. If you need comments, consider YAML or TOML instead, or use a JSON preprocessor that strips comments before parsing.

Why does YAML treat "NO" as false?

In YAML 1.1, the values yes/no, on/off, and true/false are all recognized as boolean values (case-insensitive). So the country code "NO" is interpreted as boolean false. This is known as the "Norway problem." To avoid it, always quote string values that could be misinterpreted: use "NO" instead of NO. YAML 1.2 restricts booleans to only true/false, but many parsers still use YAML 1.1 rules by default.

Is TOML better than YAML for configuration files?

TOML is often considered better for simple, flat configuration files because it has no implicit type coercion and is less error-prone than YAML. However, YAML handles deeply nested and complex structures more gracefully. For Rust and Python ecosystems, TOML is the standard choice. For DevOps and Kubernetes, YAML remains dominant.

Can I convert between JSON, YAML, and TOML without data loss?

For most common data structures (strings, numbers, booleans, arrays, objects), conversion between all three formats is lossless. However, some features are format-specific: YAML anchors and custom tags have no equivalent in JSON or TOML; TOML datetime types may lose precision in JSON; and JSON does not support comments, so converting from YAML/TOML to JSON will lose all comments.

Convert between JSON and YAML instantly with our free tool β†’

Convert between TOML and YAML with our free tool β†’

𝕏 Twitterin LinkedIn
Was this helpful?

Stay Updated

Get weekly dev tips and new tool announcements.

No spam. Unsubscribe anytime.

Try These Related Tools

Y{}JSON ↔ YAML ConverterTYTOML ↔ YAML{ }JSON FormatterYMLYAML Validator & Formatter

Related Articles

Cron Expression Generator & Examples: Every 5 Min, Daily, Weekly, Monthly

Free cron expression generator with examples. Learn cron syntax for every 5 minutes, hourly, daily, weekly, monthly schedules. Test and validate cron jobs online.

Docker Compose YAML Validation: 10 Common Syntax Errors and How to Fix Them

Stop wasting time on Docker Compose YAML errors. Learn to identify and fix the 10 most common syntax mistakes.