Which one to use
The useful split is not technical, it is about the author. JSON is what programs write and read: it is generated, transmitted, and parsed without a human in the loop. YAML is what people write by hand and then read again six months later.
That single question resolves most cases. An HTTP API returns JSON β YAML would buy nothing, and every client already has a parser. A CI pipeline, a Kubernetes manifest, or an app config is YAML, because a person maintains it and needs to leave notes explaining why a timeout is 45 seconds.
- Wire format, machine-to-machine β JSON. Smaller, universally parsed, no ambiguity to resolve.
- Config a human edits β YAML. Comments and less punctuation are the entire reason it exists.
- Data you store and query β JSON. Databases index it; almost none index YAML.
- Anything untrusted β JSON. Its grammar is tiny, which leaves far less to get wrong.
What actually differs
YAML 1.2 is a superset of JSON: any valid JSON document is also valid YAML. The reverse is not true, and the gaps are where conversion loses things.
| JSON | YAML | |
|---|---|---|
| Comments | Not allowed at all | # to end of line |
| Structure | Braces and brackets | Indentation, or braces |
| Quoting strings | Always required | Optional, which is the catch |
| Trailing commas | Rejected | Not applicable |
| Duplicate keys | Last one wins, silently | An error in strict parsers |
| Multi-line strings | \n escapes only | | and > blocks |
| Anchors and reuse | None | &anchor and *ref |
Converting JSON to YAML
A nested payload converts cleanly, and the result is genuinely shorter β the punctuation JSON needs is carried by indentation instead. Arrays sit at their parent's indent level, which is the common house style and what most linters expect.
Note what happened to env: an array of objects becomes a list of dashes, with each object's first key inlined on the dash and the rest indented under it. That is the shape Kubernetes and GitHub Actions both use.
Input JSON
{
"service": "api",
"replicas": 3,
"ports": [8080, 8443],
"env": [
{ "name": "LOG_LEVEL", "value": "debug" },
{ "name": "REGION", "value": "eu" }
],
"limits": { "cpu": "500m", "memory": "512Mi" }
}Output YAML
service: api replicas: 3 ports: - 8080 - 8443 env: - name: LOG_LEVEL value: debug - name: REGION value: eu limits: cpu: 500m memory: 512Mi
/json-to-yaml/ converter. Empty objects and arrays stay visible as {} and [] rather than becoming blank lines you cannot see.The quoting trap
This is the one that costs real time, and it only bites in the YAML direction. In JSON, "01234" is unmistakably a string, because strings are always quoted. In YAML, quotes are optional β so a parser has to guess, and it guesses from the characters.
Converting out of JSON is safe, because the tool knows what it started with. Anything that would be re-read as a number or a boolean gets quoted on the way out:
Input JSON
{
"zip": "01234",
"version": "1.10",
"enabled": "yes"
}Output YAML
zip: "01234" version: "1.10" enabled: "yes"
Why hand-written YAML loses data
Now the same three fields typed by hand, without quotes. This is the failure people hit, and nothing warns them:
- Leading zeros β postcodes, phone numbers, and account IDs all lose them.
01234becomes1234. - Trailing zeros β
1.10becomes1.1, so a version string stops matching. - `yes` and `no` β our parser keeps these as strings, matching YAML 1.2. Older 1.1 parsers, including PyYAML's default, turn
nointofalse. This is the Norway problem: the country codeNObecomes a boolean.
Hand-written YAML
zip: 01234 version: 1.10 enabled: yes
Parsed as JSON
{
"zip": 1234,
"version": 1.1,
"enabled": "yes"
}1.10 became 1.1, and a postcode is now arithmetic. All three are real output from /yaml-to-json/.What survives a round trip
JSON to YAML and back is lossless, because the quoting is written for you. Hand-written YAML to JSON and back is not, and the loss happens on the way in, before any conversion runs.
So the safe habit is one rule: quote every string in YAML that could be read as something else. Numbers stored as text are the whole category β identifiers, versions, postcodes, country codes, anything with a leading zero.
- Comments do not survive in either direction. JSON has nowhere to put them, so a conversion drops every
#line. - Anchors and aliases are expanded, not preserved β reuse becomes repetition.
- Key order is kept, which matters more for reviewing a diff than for correctness.
Try it, or read further
- JSON to YAML converterQuotes ambiguous strings for you, so the output is safe to re-parse.
- YAML to JSON converterPaste hand-written YAML here to see what a parser actually reads.
- Can JSON have comments?The other reason people move config to YAML, and the alternatives.
- Complete JSON guideSyntax, types, and the rules behind the errors.