Comparison

JSON vs YAML: Which Format Wins for Config Files in 2026?

10 min read

JSON and YAML solve the same fundamental problem - representing structured data as text - but they make very different design choices. JSON prioritizes machine-readability and strict syntax. YAML prioritizes human-readability and expressiveness. Those different starting points ripple through every decision each format makes, from how strings are quoted to whether comments are allowed. Understanding the tradeoffs helps you pick the right tool instead of defaulting to whichever one you used last.

A Brief History

JSON was formalized by Douglas Crockford in the early 2000s, extracted from the JavaScript object literal syntax. Its design philosophy is extreme simplicity: six data types, no comments, no ambiguity. Crockford wanted a format that any language could parse with minimal code, and he succeeded.

YAML (originally "Yet Another Markup Language," later rebranded to "YAML Ain't Markup Language") was first proposed in 2001 by Clark Evans. It was designed to be a human-friendly data serialization format, emphasizing readability over parsing simplicity. Here is the key relationship between the two: YAML is actually a superset of JSON - every valid JSON document is also valid YAML.

Syntax Side by Side

The same server configuration expressed in both formats reveals their differences immediately:

// JSON - config.json
{
  "server": {
    "host": "0.0.0.0",
    "port": 3000,
    "ssl": true,
    "cors": {
      "origins": ["https://example.com", "https://staging.example.com"],
      "methods": ["GET", "POST", "PUT", "DELETE"]
    }
  },
  "database": {
    "url": "postgresql://localhost:5432/myapp",
    "pool": {
      "min": 2,
      "max": 10
    }
  },
  "logging": {
    "level": "info",
    "format": "json"
  }
}
# YAML - config.yaml
server:
  host: 0.0.0.0
  port: 3000
  ssl: true
  cors:
    origins:
      - https://example.com
      - https://staging.example.com
    methods:
      - GET
      - POST
      - PUT
      - DELETE

database:
  url: postgresql://localhost:5432/myapp
  pool:
    min: 2
    max: 10

logging:
  level: info
  format: json

The YAML version is roughly 30% shorter. No curly braces, no quotation marks around most strings, no commas. But that brevity introduces ambiguity that JSON deliberately avoids - and that ambiguity has real consequences we will get to shortly.

Comments: YAML's Biggest Advantage

JSON has no comment syntax. This is by design - Crockford removed comments to prevent people from using them as parsing directives - but it is a genuine pain point for configuration files. You cannot explain why a setting exists, document valid ranges, or leave notes for the next developer who touches the file.

YAML supports comments with the # character:

# Maximum connections to the database
# Increase this if you see pool exhaustion errors in production
pool:
  min: 2   # Keep at least 2 connections warm
  max: 10  # Don't exceed the DB's max_connections setting

This alone is reason enough to prefer YAML for configuration files that humans edit regularly. JSON workarounds exist - using a _comment key, adopting JSON5, or using JSONC - but none are part of the actual JSON specification.

Multiline Strings

YAML handles multiline strings elegantly with block scalars. The pipe character (|) preserves newlines exactly as written, and the greater-than sign (>) folds them into spaces:

# Preserves newlines exactly
description: |
  This is a multi-line
  description that keeps
  its line breaks.

# Folds into a single paragraph
summary: >
  This is a long description
  that will be folded into
  a single line.

In JSON, multiline strings are a mess of \n escape sequences crammed into a single line. For configuration that includes SQL queries, email templates, or shell scripts, YAML is significantly more readable.

Anchors and Aliases

YAML has a built-in DRY feature that lets you define a value once and reference it elsewhere using anchors (&) and aliases (*):

defaults: &default_settings
  timeout: 30
  retries: 3
  backoff: exponential

services:
  user-api:
    <<: *default_settings
    url: https://users.internal
  payment-api:
    <<: *default_settings
    timeout: 60  # Override the default for this service
    url: https://payments.internal

JSON has no equivalent. You would need to either duplicate the values or handle the merging in your application code. For complex configurations with shared defaults across many services, anchors reduce repetition significantly.

JSON's Strictness Is an Advantage

JSON's rigid syntax means there is only one way to represent any given data structure. This makes it predictable and trivial to parse correctly. Every JSON parser in every language produces the same result for the same input. You cannot say that about YAML.

Consider the specification sizes: JSON's grammar fits in a few dozen lines. YAML's specification runs over 80 pages. That complexity translates directly into implementation inconsistencies - different YAML parsers can interpret the same document differently, especially around edge cases involving type coercion. When correctness matters more than convenience, JSON's strictness is a feature, not a limitation.

Where YAML Dominates

Some ecosystems have standardized on YAML and you do not really get a choice:

The common thread: these are configuration files that humans write and read frequently, where comments and readability matter more than parsing strictness.

Where JSON Dominates

Common YAML Pitfalls

YAML's implicit type coercion causes real bugs in production. Here are the ones that bite developers most often:

The Norway Problem

In YAML 1.1, the values yes, no, on, off, true, and false are all treated as booleans. This became infamous when developers discovered that country codes like NO (Norway) were silently converted to false:

# You think this is a string...
country: NO

# ...but YAML parses it as boolean false
# { country: false }

YAML 1.2 reduced this problem by only recognizing true and false as booleans, but many parsers still default to YAML 1.1 behavior.

Indentation Sensitivity

A single extra or missing space can change the structure of a YAML document entirely. Unlike Python, where indentation errors produce clear error messages, YAML will often parse silently but produce a different structure than you intended:

# Intended: two separate keys under "server"
server:
  host: localhost
  port: 3000

# Accidentally wrote: "port" is a separate top-level key
server:
  host: localhost
port: 3000

Unexpected Type Coercion

version: 1.0    # Parsed as float 1.0, not string "1.0"
version: 1.10   # Parsed as float 1.1 - trailing zero is lost
phone: 012345   # Parsed as octal number 5349 in YAML 1.1
time: 12:30     # Parsed as the integer 750 (sexagesimal) in some parsers

The fix is to quote strings explicitly: version: "1.10". But this defeats one of YAML's main selling points - not needing quotes - and forgetting to do it produces subtle bugs that can take hours to track down.

Which Should You Choose?

The answer depends on who reads and writes the file and what ecosystem you are working in:

Both formats have rough edges. JSON's lack of comments is frustrating for config files. YAML's implicit type coercion is genuinely dangerous. Know the tradeoffs and pick the tool that fits the job. If you want a deeper comparison of JSON against its older rival, read our guide to JSON vs XML.

Working with JSON Config Files?

Format and validate them instantly in your browser with our free tool.

Open JSON Prettifier