You've probably noticed that some projects use .json files for config while others
use .yaml or .yml. Both formats represent structured data. Both are human-readable.
So what's the actual difference, and when should you reach for one over the other?
I've used both extensively — JSON is my daily driver for APIs and data exchange, YAML is my go-to for Kubernetes manifests, GitHub Actions, and Docker Compose. They solve similar problems but they have very different personalities.
Side by Side: The Same Config in Both Formats
Here's a database config object written in JSON:
{
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp",
"ssl": true,
"pool": {
"min": 2,
"max": 10
},
"replicas": ["replica1.db", "replica2.db"]
}
}And here's the same config in YAML:
database:
host: localhost
port: 5432
name: myapp
ssl: true
pool:
min: 2
max: 10
replicas:
- replica1.db
- replica2.dbYAML is visibly less cluttered. No quotes around most strings, no curly braces, no commas. For a config file that humans edit regularly, that clarity adds up. But YAML achieves this by being significantly more complex under the hood.
Where YAML Shines
- Human-editable config files. CI/CD pipelines (GitHub Actions, GitLab CI), Kubernetes manifests, Docker Compose, Ansible playbooks. All YAML. No coincidence — these are files humans write by hand.
- Comments. YAML supports comments with
#. This is huge for config files where you want to explain why a setting is what it is. JSON doesn't support comments at all. - Multi-line strings. YAML has block scalars for multi-line content that read naturally. JSON requires
\nescape sequences. - Less visual noise. No requirement to quote most strings, no closing braces, no trailing commas to worry about.
- Anchors and aliases. YAML lets you define a value once and reference it elsewhere with
&anchorand*alias— handy for DRY config files.
Where JSON Wins
- Strictness. JSON has one valid representation for any given data structure. YAML has a dozen ways to write the same thing, which creates inconsistency across teams.
- No indentation traps. JSON uses braces and brackets. YAML uses indentation, which means a single misplaced space can silently break your entire config.
- Parse performance. JSON parsers are fast and simple. YAML parsers are complex — YAML 1.1 has notoriously tricky implicit type coercion rules.
- Universal library support. Every language has a battle-tested, zero-dependency JSON parser. YAML libraries vary in quality and spec compliance.
- Tooling. Linters, formatters, schema validators — JSON tooling is more mature and widely available.
- API payloads. JSON is the universal language of web APIs. Sending YAML over HTTP would be unconventional and cause friction.
The YAML Gotchas That Will Burn You
YAML has some genuinely surprising behaviours that have caused real production incidents. Most of them come from the implicit type rules in YAML 1.1, which YAML 1.2 tightened up. Know these before you rely on YAML for anything critical:
NO
is parsed as boolean false. Country codes like NO (Norway), NO, and others
get silently converted to booleans. YAML 1.2 fixed this, but not all parsers have caught up.# YAML 1.1 implicit type coercion — all of these become booleans:
enabled: yes # → true
disabled: no # → false
country: NO # → false (!) ← the Norway Problem
# Safe practice: quote strings that look like booleans
country: "NO"
enabled: "yes"- Octal integers. In YAML 1.1,
010parses as8(octal), not10. Relevant for things like file permissions. - Tabs vs spaces. YAML forbids tabs for indentation. Mix in one tab from a code editor and your file breaks silently or throws a cryptic error.
- Implicit nulls. An empty value in YAML becomes null. Easy to miss when editing by hand.
- String vs number ambiguity.
port: 8080gives you an integer.version: 1.0might give you a float. Sometimes you want the string"1.0". Always quote when it matters.
Practical Decision Guide
Reach for YAML when:
- Writing config files that humans edit directly: CI/CD, Kubernetes, Docker Compose, Ansible
- The file will have comments explaining the settings
- Multi-line string values are common
- The ecosystem you're working in already uses YAML (don't fight the convention)
Reach for JSON when:
- Sending or receiving data over an API
- The data is generated and consumed programmatically (no human editing)
- You need guaranteed parse consistency across different tools and languages
- Working in an ecosystem that standardises on JSON: npm (package.json), VS Code (settings.json), Angular, TypeScript
Converting Between the Two
Need to convert YAML config into JSON for a tool that doesn't speak YAML? Use the YAML to JSON converter. Going the other way? The JSON to YAML converter will handle it. The YAML Formatter is also handy when you paste YAML that's gotten misaligned. And if your YAML won't parse, the YAML Validator will tell you exactly where the problem is.
The Bottom Line
JSON and YAML are complementary, not competing. Use JSON for data exchange — APIs, programmatic
data storage, serialisation. Use YAML for config files that humans read and edit. Most mature projects
use both: package.json for dependencies, .github/workflows/*.yml for CI.
Once you understand what each format is optimised for, the choice becomes obvious.