TL;DR: JSON is strict, machine-friendly, and great for APIs. YAML is human-readable, supports comments, and dominates config files (Kubernetes, Docker Compose, GitHub Actions). Neither is "better" — they're good at different things. Converting between them is straightforward with the right tools.
If you've worked with modern dev tools for more than five minutes, you've touched both JSON and YAML. Your package.json is JSON. Your docker-compose.yml is YAML. Your brain switches between curly braces and indentation several times a day. Let's clear up the differences once and for all.
JSON: The Strict One
JSON (JavaScript Object Notation) was formalized by Douglas Crockford in the early 2000s. It's a no-nonsense format with very rigid rules:
{
"name": "CodeToolsPro",
"version": "2.1.0",
"private": true,
"dependencies": {
"express": "^4.18.0",
"cors": "^2.8.5"
},
"scripts": {
"start": "node server.js",
"test": "jest --coverage"
}
}
The rules are simple and unforgiving:
- Keys MUST be double-quoted strings (single quotes? nope).
- No comments allowed. (This drives everyone absolutely nuts.)
- No trailing commas. (Also infuriating.)
- Data types are crystal clear —
"true"is a string,trueis a boolean. - Every browser can parse it natively with
JSON.parse().
YAML: The Chill One
YAML (YAML Ain't Markup Language — yes, it's a recursive acronym) takes a more relaxed approach:
name: CodeToolsPro
version: "2.1.0"
private: true
dependencies:
express: "^4.18.0"
cors: "^2.8.5"
scripts:
start: node server.js
test: jest --coverage
Same data, but look how much cleaner that looks! YAML trades braces and quotes for indentation. It's like JSON went on vacation and came back wearing a Hawaiian shirt.
Side-by-Side Showdown
| Feature | JSON | YAML |
|---|---|---|
| Comments | Not supported | Supported (#) |
| Readability | Moderate | High |
| Strictness | Very strict | Flexible (sometimes too flexible) |
| File size | Larger (braces, quotes) | Smaller |
| Parsing speed | Fast | Slower |
| Multi-line strings | Escaped newlines only | Block scalars (| and >) |
| Browser support | Native | Requires a library |
| Primary use | APIs, data exchange | Configuration files |
YAML Gotchas That'll Ruin Your Day
The Norway Problem
Fun Fact: In YAML 1.1, the value NO gets interpreted as boolean false. This famously broke country code lists where Norway (NO) magically became false. Poor Norway — rejected by YAML itself.
YAML 1.2 fixed this, but many parsers still use 1.1 rules. Always quote ambiguous strings:
# Dangerous
country: NO # Parsed as false in YAML 1.1!
# Safe
country: "NO" # Always a string
The Invisible Indentation Trap
YAML is whitespace-sensitive, and a single extra or missing space can silently change your data's meaning. Use consistent 2-space indentation and a linter like yamllint. Your future self will thank you.
Multiline Strings Are Actually Great
This is where YAML genuinely shines:
# Literal block (|) — preserves every newline
description: |
This is line one.
This is line two.
Each newline is kept exactly as-is.
# Folded block (>) — joins lines into one paragraph
description: >
This is a long paragraph
that will be joined into
a single line with spaces.
Try doing that cleanly in JSON. (Spoiler: you can't.)
Converting Between Them
Python
import json, yaml
# JSON to 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, sort_keys=False)
# YAML to JSON
with open('config.yaml') as f:
data = yaml.safe_load(f) # Always use safe_load!
with open('config.json', 'w') as f:
json.dump(data, f, indent=2)
Security Warning: Always use yaml.safe_load(), never yaml.load(). The unsafe version can execute arbitrary Python objects hidden in YAML files — it's a well-known security vulnerability.
Node.js
import { readFileSync, writeFileSync } from 'fs';
import YAML from 'yaml';
const data = JSON.parse(readFileSync('config.json', 'utf8'));
writeFileSync('config.yaml', YAML.stringify(data));
Command Line (using yq)
# JSON to YAML
yq -P config.json > config.yaml
# YAML to JSON
yq -o=json config.yaml > config.json
When to Pick JSON
- API responses: JSON is THE universal format for REST APIs.
- Machine-to-machine data: When humans rarely read the file.
- Browser environments: Native
JSON.parse()is fast and everywhere. - Strict typing matters: JSON's rigidity prevents ambiguous values.
- Ecosystem conventions:
package.json,tsconfig.json— don't fight convention.
When to Pick YAML
- Config files: Docker Compose, Kubernetes manifests, CI/CD pipelines.
- Human-edited files: When devs frequently read and modify by hand.
- You need comments: Documenting WHY a setting exists is invaluable.
- Multi-line strings: YAML's block scalars are lightyears ahead of escaped JSON strings.
Pro Tip: Fun fact — valid JSON is technically valid YAML (since YAML 1.2). So if someone asks you to convert JSON to YAML, you could just... rename the file. (Please don't actually do this.)
The Bottom Line
Neither format is universally better. JSON excels at machine-to-machine communication with its strict, unambiguous syntax. YAML excels at human-facing configuration with its readability and comment support. Most developers need fluency in both, and being able to convert between them quickly is a practical skill that saves time every single day.
Try It Yourself
Paste JSON and get YAML, or paste YAML and get JSON — instantly in your browser with our free converter.
Open JSON-YAML Converter →