JSON and YAML are both text-based formats for representing structured data, and both appear constantly in modern software development. JSON dominates REST APIs and browser applications; YAML dominates CI/CD pipelines, Kubernetes, and configuration files. Understanding the trade-offs helps you pick the right format and avoid the surprising pitfalls each one carries.
Side-by-Side Syntax Comparison
The same application configuration written in both formats:
JSON:
{
"app": "my-service",
"version": "2.1.0",
"server": {
"host": "0.0.0.0",
"port": 8080,
"debug": false
},
"database": {
"host": "db.example.com",
"ssl": true
},
"allowedOrigins": [
"https://app.example.com",
"https://www.example.com"
],
"description": "Main API service"
}
YAML:
# Application configuration
app: my-service
version: "2.1.0"
server:
host: "0.0.0.0"
port: 8080
debug: false
database:
host: db.example.com
ssl: true
allowedOrigins:
- https://app.example.com
- https://www.example.com
description: Main API service
YAML is visibly less noisy β no braces, fewer quotes, and comments are allowed. JSON is more explicit about every boundary.
YAML Advantages
Comments. YAML supports # comments. JSON does not. This is the most practically important difference for config files that humans edit:
# Database settings β update host before deploying to production
database:
host: db.prod.example.com # change this for staging
port: 5432
Multi-line strings. YAML has two block scalar styles. The literal block (|) preserves newlines; the folded block (>) folds them into spaces:
message: |
Dear user,
Your account has been created.
Welcome aboard!
summary: >
This text spans multiple
lines but will be joined
into a single line.
Anchors and aliases (DRY config). YAML lets you define a block once and reuse it with & and *:
defaults: &defaults
retries: 3
timeout: 30
production:
<<: *defaults
host: prod.example.com
staging:
<<: *defaults
host: staging.example.com
JSON Advantages
Strict syntax β fewer surprises. JSON has one way to write every value. YAML has many, and they interact unexpectedly. JSON parse errors are rare after learning the four rules (double quotes, no trailing commas, no comments, no unquoted keys). YAML parse errors are often invisible β the parser accepts the file but silently produces the wrong value.
Universal browser and API support. Every browser supports JSON.parse() natively. Every REST framework defaults to JSON. YAML requires a library in virtually every language. For HTTP APIs, configuration-as-code that runs in the browser, and database documents, JSON is the practical default.
Faster to parse. JSON parsers are highly optimized because the format is so simple. YAML parsers must handle indentation sensitivity, implicit type coercion, multiple quoting styles, anchors, and more β making them slower and harder to implement correctly.
YAML Gotchas You Must Know
The Norway problem (implicit boolean coercion). In YAML 1.1 (used by many tools including older Kubernetes versions), unquoted country codes like NO, yes, on, off are parsed as booleans. NO becomes false. This breaks locale codes, toggle names, and short keys silently:
# Dangerous in YAML 1.1
countries:
- NO # parsed as false, not the string "NO"
- GB
- US
# Safe: always quote ambiguous values
countries:
- "NO"
- GB
- US
Indentation is structural. A single wrong indent level moves a key to the wrong parent object. JSON uses braces, so indentation is cosmetic. In YAML it is syntax:
# WRONG β logging is a sibling of server, not a child
server:
host: localhost
logging: # intended to be under server
level: debug
# CORRECT
server:
host: localhost
logging:
level: debug
Strings that look like other types. Unquoted values are type-coerced. Version numbers, port numbers written as strings, and other values can be misinterpreted:
version: 1.10 # parsed as float 1.1, not string "1.10"
version: "1.10" # correct β string preserved
port: 8080 # fine β integer
country: NO # problem β boolean false in YAML 1.1
Where Each Format Wins
| Use Case | Best Choice | Why |
|---|---|---|
| REST API response | JSON | Native browser support, universal client expectation |
| Kubernetes manifests | YAML | Less verbose, comments, official format for K8s |
| GitHub Actions workflow | YAML | Multiline scripts, comments, official format |
| Docker Compose | YAML | Anchors for shared config, readability |
package.json / tsconfig.json
|
JSON | Node.js tooling expects JSON |
| Database documents | JSON | MongoDB, Firestore, DynamoDB use JSON natively |
| Human-edited app config | YAML | Comments explain intent; less punctuation to misplace |
| Machine-generated config | JSON | Easier to generate correctly; no indentation to manage |
YAML Is a JSON Superset (With Caveats)
The YAML 1.2 specification states that JSON is valid YAML. In practice, most YAML parsers accept valid JSON. This means you can gradually migrate a JSON config to YAML by renaming it and adding comments without changing any values. However, don't rely on this in production without testing β older YAML 1.1 parsers have edge cases where valid JSON is rejected.
Quick Decision Guide
- Writing a REST API? Use JSON.
- Writing a CI/CD pipeline (GitHub Actions, GitLab CI, CircleCI)? Use YAML.
- Writing Kubernetes or Helm charts? Use YAML.
- Writing a config file that humans edit frequently and need to annotate? Use YAML.
- Generating config programmatically from code? JSON is safer to generate correctly.
- Storing data in a database or sending over HTTP? JSON.
Converting Between JSON and YAML
Since YAML 1.2 is a superset of JSON, most YAML parsers can read valid JSON directly. Going the other way β YAML to JSON β requires a YAML parser and a JSON serializer.
Python β bidirectional conversion:
import json
import yaml # pip install pyyaml
# JSON β YAML
with open('config.json') as f:
data = json.load(f)
with open('config.yaml', 'w') as f:
yaml.dump(data, f, default_flow_style=False, allow_unicode=True)
# YAML β JSON
with open('config.yaml') as f:
data = yaml.safe_load(f)
with open('config.json', 'w') as f:
json.dump(data, f, indent=2)
Node.js β bidirectional conversion:
const fs = require('fs');
const yaml = require('js-yaml'); // npm install js-yaml
// JSON β YAML
const data = JSON.parse(fs.readFileSync('config.json', 'utf8'));
fs.writeFileSync('config.yaml', yaml.dump(data));
// YAML β JSON
const loaded = yaml.load(fs.readFileSync('config.yaml', 'utf8'));
fs.writeFileSync('config.json', JSON.stringify(loaded, null, 2));
Command line with yq:
# JSON β YAML
yq -o=yaml config.json > config.yaml
# YAML β JSON
yq -o=json config.yaml > config.json
# Query YAML (like jq for YAML)
yq '.server.port' config.yaml
Linting and Validation
Both formats benefit from automated checks in CI/CD pipelines to catch syntax errors before they reach production.
JSON linting:
-
jqβjq . file.json > /dev/nullexits with a non-zero code if the file is invalid JSON. Simple and fast. - JSON Schema β validates not just syntax but structure and data types.
- ESLint β for JavaScript projects, can flag invalid inline JSON and enforce
JSON.parseerror handling.
YAML linting:
-
yamllintβpip install yamllint, thenyamllint config.yaml. Catches indentation issues, duplicate keys, and trailing spaces. -
kubeval/kubeconformβ validates Kubernetes YAML manifests against the official schema. Catches wrong field names and types beforekubectl apply. - GitHub Actions schema validation β the official VS Code YAML extension can validate workflow files against the GitHub Actions JSON Schema automatically.
TOML: A Third Option Worth Knowing
TOML (Tom's Obvious Minimal Language) is increasingly common for developer tooling configuration β Rust's Cargo.toml, Python's pyproject.toml, and Hugo static site configs use it. TOML is more opinionated than YAML (no implicit types, strict date handling) and more readable than JSON for config files with many sections. It's not suitable for data exchange or APIs β only for configuration. If you see a .toml file, it occupies a niche between JSON's strictness and YAML's readability.
Need to format, validate, or fix JSON right now? JSON Formatter Hub does it entirely in your browser β free, no uploads.













