YAML vs JSON: what's the difference?
YAML and JSON describe the same kinds of data: objects, lists, strings, numbers, booleans. Anything you can write in one, you can write in the other. The difference is who they are written for. JSON is built for machines exchanging data; YAML is built for humans editing files.
That is why APIs speak JSON while Docker Compose, Kubernetes, and GitHub Actions expect YAML — and why developers end up converting between the two constantly.
The same data in both formats
Here is a small service definition in JSON:
{
"service": "api",
"replicas": 2,
"env": {
"NODE_ENV": "production",
"PORT": 8080
},
"depends_on": ["db", "cache"]
}
Strict and unambiguous — but every key is quoted and every block is wrapped in braces.
And the identical data in YAML:
service: api replicas: 2 env: NODE_ENV: production PORT: 8080 depends_on: - db - cache
No quotes, no braces, no commas. Structure comes from indentation.
Nothing was lost in translation. YAML simply trades explicit punctuation for whitespace, which makes it easier to read and edit — and easier to break.
Where JSON wins
- Strictness. There is exactly one way to write a JSON document. No indentation rules, no implicit typing, no surprises in how a value is parsed.
- Universality. Every language ships a JSON parser, every API speaks it, and tools like
jqare built around it. - Machine interchange. When two programs exchange data, JSON's rigidity is a feature: a payload either parses or it does not.
Where YAML wins
- Readability. Less punctuation means config files that are easy to scan and diff in a pull request.
- Comments. YAML supports
#comments; JSON has none. For configuration that humans maintain, this alone often decides it. - Multiline strings. Block scalars (
|and>) hold scripts and certificates without escape-character soup. - The config ecosystem. Docker Compose, Kubernetes, GitHub Actions, GitLab CI, Ansible — the modern ops stack standardized on YAML.
YAML pitfalls to know
YAML's flexibility has a price, and it is worth knowing the classics before they bite:
- Indentation is the syntax. One wrong space changes the structure of the document, and tabs are not allowed at all. Most "broken pipeline" YAML bugs are indentation bugs.
- The Norway problem. In older YAML 1.1 parsers, the unquoted value
nois read as the booleanfalse— so a country list containing Norway's codeNOquietly corrupts. Modern YAML 1.2 parsers treat it as a string, but plenty of tooling in the wild still behaves the 1.1 way. When in doubt, quote it. - Implicit typing. Is
3.10a version string or the number 3.1? Is08:30a time? Unquoted scalars can be guessed in ways you did not intend.
A quick sanity check: convert the YAML to JSON and look at the result. JSON has no implicit types, so whatever the parser actually understood becomes visible immediately.
When to convert between them
YAML to JSON is the direction for using config data programmatically: feeding a CI config to a script, querying it with jq, sending it to an API that expects JSON, or simply debugging what a YAML file really contains. MarkDone's YAML to JSON converter does this in your browser, including anchors, aliases, and multiline strings.
JSON to YAML goes the other way: an API response or an example payload from documentation needs to become a readable config block in docker-compose.yml or a Kubernetes manifest. MarkDone's JSON to YAML converter produces clean, 2-space-indented YAML ready to paste.
Both converters run entirely locally. That matters more for configs than for most data, because real-world YAML files routinely contain tokens, internal hostnames, and credentials that have no business being pasted into a random online converter.
YAML to JSON JSON to YAML
Working with structured data in AI prompts instead? JSON has a token-efficient sibling there too — read what is TOON?