YAML vs JSON: The Real Differences and When to Use Each
You've written a Kubernetes manifest in YAML, a package.json in JSON, a GitHub Actions workflow in YAML, and an API response in JSON — all before lunch. The two formats are everywhere, they store the same kinds of data, and yet they feel completely different to work with. One is human-friendly, the other is machine-friendly, and knowing which is which will save you a surprising number of debugging sessions.
What they actually are
JSON (JavaScript Object Notation) was created by Douglas Crockford around 2001 as a minimal, language-independent way to transmit structured data. It has six data types: objects, arrays, strings, numbers, booleans, and null. Nothing else. The spec fits on a single page, which is most of its appeal.
YAML (YAML Ain't Markup Language — yes, it's a recursive acronym) was designed as a human-readable data serialization language. The first spec came out in 2001 too, but YAML has been revised multiple times. It is a superset of JSON, meaning any valid JSON is also valid YAML. But YAML adds a lot more: comments, multi-line strings, anchors and aliases, multiple document streams, and far more implicit type coercion.
That last point — implicit type coercion — is where most of the pain comes from.
The same data, side by side
Here's a simple config object in both formats:
# YAML
name: my-service
port: 8080
debug: false
tags:
- web
- production
database:
host: db.internal
port: 5432
// JSON
{
"name": "my-service",
"port": 8080,
"debug": false,
"tags": ["web", "production"],
"database": {
"host": "db.internal",
"port": 5432
}
}
The YAML version is shorter and has no quotes around most strings. It uses indentation to express nesting instead of brackets and braces. For a human editing a config file, it's faster to write and easier to scan.
The JSON version is more verbose, but every value is explicit. There's no ambiguity about types, and a parser has to do almost no work to interpret it.
Where YAML quietly breaks things
YAML's implicit type coercion is its most dangerous feature. A value that looks like a string might be interpreted as a boolean, a number, a null, or an octal literal depending on the parser and the YAML version.
The classic example:
country: NO
enabled: yes
version: 1.0
id: 077
In YAML 1.1 (which most parsers still use by default): NO becomes false, yes becomes true, 1.0 becomes a float, and 077 becomes 63 — the octal value of 077.
This has caused real production incidents. A two-letter country code NO (Norway) getting parsed as boolean false. A version string 1.0 stored as a float instead of a string. An ID with a leading zero silently converted to a different number.
The fix is to quote these values explicitly: country: "NO", version: "1.0". But you have to know to do it, and nothing in the syntax warns you that it's necessary.
When to use JSON
APIs and data interchange. JSON is the correct choice for any data that crosses a service boundary. It's unambiguous, universally supported, and parseable in every language without a specialized library. Implicit type coercion that trips up a human editing a file will trip up a machine parsing a network response too — JSON avoids this entirely.
Data storage. If you're storing structured data in a database column, a log file, or a cache entry, use JSON. It's compact when minified, unambiguous, and readable when formatted. YAML's indentation-sensitive structure makes it fragile to store in systems that might reformat whitespace.
package.json, tsconfig.json, .eslintrc. These are JSON by convention. Editors have first-class support for them. Don't add complexity by switching to YAML equivalents unless you have a specific reason.
When machines are the primary consumer. If the primary reader of the file is a program rather than a person, JSON's explicit syntax makes parsing faster, more predictable, and less prone to version-specific surprises.
When to use YAML
Configuration files humans edit regularly. Kubernetes manifests, Docker Compose, Ansible playbooks, GitHub Actions workflows, Helm charts — all YAML. The format was chosen for these because the files are large, humans edit them directly, and readability matters more than machine-parsing convenience.
When you need comments. JSON has no comment syntax. YAML does: # this is a comment. For config files where you want to explain why a value is set, or leave notes for the next person, YAML's comments are invaluable. This is the single biggest practical advantage YAML has over JSON for config management.
Multi-line strings. YAML handles multi-line strings cleanly with block scalar syntax. The | literal block preserves newlines, and > folded block collapses them. Writing a multi-line string in JSON requires explicit \n escape sequences, which is painful to read and write.
Anchors and aliases for DRY configs. YAML lets you define a block once with an anchor (&name) and reference it elsewhere with an alias (*name). If you have a large config with repeated sections — common in CI pipelines and Kubernetes — this can significantly reduce duplication.
The YAML version problem
YAML 1.1 and YAML 1.2 behave differently. YAML 1.2 (released 2009) removed the boolean coercion for yes/no/on/off and octal literals, and explicitly made YAML a superset of JSON. But most tools — including many Kubernetes libraries, Python's PyYAML, and Ruby's Psych — still default to YAML 1.1 behavior for backwards compatibility.
This means you can't always predict which version a tool is using, and the safe assumption is YAML 1.1. Quote anything that might be coerced: ISO country codes, version strings, values that look like numbers with leading zeros, and anything that could be interpreted as a boolean in any language.
Practical rules
- Use JSON for APIs, data exchange, and machine-consumed config.
- Use YAML for human-edited config files, especially when comments or multi-line values matter.
- Always quote string values in YAML that could be misinterpreted:
YES,NO,ON,OFF,TRUE,FALSE,NULL, version numbers, IDs with leading zeros. - Never rely on YAML anchors in data that will be stored — they're resolved at parse time and don't survive serialization to JSON.
- Validate YAML in CI. A missing space in indentation is a runtime error waiting to happen.
YAML ↔ JSON Converter — Paste YAML to get JSON or JSON to get YAML. Auto-detects the format, runs entirely in your browser.
Open Tool