JSON vs YAML: Which Format Wins for Config Files in 2026?
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: jsonThe 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 settingThis 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.internalJSON 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:
- Kubernetes - manifests, Helm charts, and everything in the cluster are YAML. The sheer volume of YAML a Kubernetes engineer writes is a running joke in the industry.
- Docker Compose -
docker-compose.ymlhas been YAML from day one. - CI/CD pipelines - GitHub Actions, GitLab CI, CircleCI, and Azure Pipelines all use YAML for workflow definitions.
- Ansible - playbooks, roles, and inventories are all YAML.
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
- REST APIs - JSON is the universal language of web APIs. Virtually every public API returns JSON by default.
- package.json, tsconfig.json, .eslintrc.json - the JavaScript ecosystem uses JSON heavily for tooling configuration.
- NoSQL databases - MongoDB, CouchDB, and DynamoDB all store JSON or JSON-like documents natively.
- Browser APIs -
localStorage, Fetch responses, and Web Storage all deal in JSON. There is no YAML equivalent in the browser.
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: 3000Unexpected 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 parsersThe 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:
- If the file is machine-generated and machine-consumed (API responses, data storage, inter-service communication) - use JSON. Its strictness prevents ambiguity and every language can parse it natively.
- If the file is written by humans and needs comments (CI/CD configs, deployment manifests, application settings) - use YAML, but quote your strings defensively to avoid type coercion surprises.
- If your ecosystem has already chosen one - do not fight it. Write
package.jsonin JSON and Kubernetes manifests in YAML. Going against the grain creates friction for every developer on the team.
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