Why convert YAML to JSON
YAML is pleasant to write by hand, but most programs want JSON. Common reasons to go in this direction:
- Feeding a config file to a REST API,
jqor a JSON Schema validator. - Checking what a tricky YAML file actually means: indentation, quoting and block scalars are easy to misread, and JSON shows the resolved values with no ambiguity.
- Storing a Helm values file or an OpenAPI spec in a system that only accepts JSON.
If you are deciding which format to keep long-term, the JSON vs YAML guide compares them.
How the YAML is read
The converter parses YAML 1.2 (the core schema) in strict mode and then writes standard JSON. That choice decides how plain, unquoted values turn into types:
trueandfalsebecome booleans,nulland~become null. Words likeyes,no,onandoffstay strings, because only YAML 1.1 readers treat them as booleans.- Integers and floats become JSON numbers.
0x1Fis read as hex (31) and0o755as octal (493);0755without theois plain decimal 755. - Unquoted dates such as
2024-01-01stay strings, since YAML 1.2 has no timestamp type. - Integers larger than 2^53 are written with all their digits instead of being rounded.
.infand.nanhave no JSON spelling and come out as null.- Literal blocks (
|) keep their line breaks; folded blocks (>) join lines with spaces.
Keys keep their order, and a file with several documents separated by --- becomes a JSON array with one element per document.
Anchors, aliases and merge keys
An anchor (&base) and its aliases (*base) are expanded: every alias is replaced by a full copy of the anchored value, which is what any program reading the YAML would see. To protect your browser from “billion laughs” files, expansion stops after 1,000 aliases and the conversion fails with an explanation instead of hanging.
The << merge key is a YAML 1.1 extension and is not applied. It survives as an ordinary key named "<<" that contains the copied mapping. If your tooling relies on merges (Docker Compose and GitLab CI do), check those keys in the output and inline the merged fields where needed.
What does not survive
JSON has nowhere to put comments, so every # comment is dropped and an info note says so. Tags such as !!str are applied and then disappear, and custom application tags lose their meaning. Anchors and aliases vanish too, replaced by the duplicated data, so the JSON can be noticeably longer than the YAML it came from.
There are no conversion options to set. Errors are reported with a line and column, and nothing is guessed: duplicate keys and tab indentation stop the conversion rather than silently picking a value.
Tips
- Quote values you want kept as text, such as version numbers (
"1.10") or ZIP codes with a leading zero, before converting. - To go back the other way, use the JSON to YAML converter; to tidy the YAML first, run it through the YAML formatter.
- The conversion runs entirely in this tab, which makes it safe for files containing tokens or connection strings.
Examples
Docker Compose style anchors
Both aliases are replaced by full copies of the anchored logging block, so the JSON shows exactly what a reader of the file receives.
x-logging: &logging
driver: json-file
options:
max-size: 10m
services:
web:
image: nginx:1.27
ports: ["8080:80"]
logging: *logging
worker:
image: acme/worker:2.3
logging: *logging
{
"x-logging": {
"driver": "json-file",
"options": {
"max-size": "10m"
}
},
"services": {
"web": {
"image": "nginx:1.27",
"ports": [
"8080:80"
],
"logging": {
"driver": "json-file",
"options": {
"max-size": "10m"
}
}
},
"worker": {
"image": "acme/worker:2.3",
"logging": {
"driver": "json-file",
"options": {
"max-size": "10m"
}
}
}
}
}
Two documents in one file
Each document separated by — becomes one element of a top-level JSON array, in the original order.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: info
FEATURE_X: "on"
---
apiVersion: v1
kind: Service
metadata:
name: app
spec:
ports:
- port: 80
targetPort: 8080
[
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "app-config"
},
"data": {
"LOG_LEVEL": "info",
"FEATURE_X": "on"
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "app"
},
"spec": {
"ports": [
{
"port": 80,
"targetPort": 8080
}
]
}
}
]
Plain scalars and their JSON types
Shows YAML 1.2 typing: yes and the date stay strings, 0755 is decimal, the huge build number keeps every digit and ~ becomes null.
enabled: yes
retries: 3
ratio: 0.75
mode: 0755
released: 2024-01-01
build: 12345678901234567890
empty: ~
{
"enabled": "yes",
"retries": 3,
"ratio": 0.75,
"mode": 755,
"released": "2024-01-01",
"build": 12345678901234567890,
"empty": null
}
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Duplicate key — keys in a mapping must be uniqueExplained | The same key appears twice at one level of a mapping, often after copy-pasting a block. | Delete or rename one of the keys. JSON parsers disagree on which duplicate wins, so the converter refuses to guess. |
Tabs are not allowed for indentation in YAMLExplained | A line is indented with a tab character; YAML only accepts spaces for indentation. | Replace the tabs with spaces (two per level is usual). Most editors can convert indentation for the whole file. |
A nested block cannot be used as a keyExplained | A line such as a: b: c puts a second colon-space where YAML expects a plain value. | Quote the value (a: "b: c") or move the nested mapping onto its own indented line. |
Plain value cannot start with reserved character @Explained | Unquoted values may not begin with @ or a backtick, which YAML reserves. | Wrap the value in quotes, for example handle: "@team". |
Too many alias expansions — this looks like a "billion laughs" alias bomb, so it was not expandedExplained | Aliases refer to anchors that themselves contain aliases, multiplying into more than 1,000 expansions. | If the file is legitimate, reduce the nesting of aliases; if it came from an untrusted source, treat it as hostile. |
Frequently asked questions
Are YAML comments kept in the JSON?
No. JSON has no comment syntax, so comments are dropped and an info message tells you that happened. Keep the YAML as the source of truth if the comments matter.
Why did "no" or "off" stay a string instead of becoming false?
The converter follows YAML 1.2, where only true and false are booleans. Older YAML 1.1 parsers such as PyYAML would read no as false, which is the well-known Norway problem; write false explicitly if that is what you mean.
What happens to a file with several documents?
All documents are converted and wrapped in a JSON array in their original order. A single document converts to its value directly, with no wrapping array.
Are very large numbers rounded?
Integers beyond JavaScript’s safe range are copied digit for digit into the JSON. Whether the program that later reads the JSON keeps them exact depends on its parser.
Is my YAML sent to a server?
No. Parsing and conversion happen in your browser, and the page makes no network request with your input.