YAML to JSON Converter
Paste a manifest, a compose file or a pipeline config. Anchors and merge keys are resolved, dates stay the strings you wrote, and the JSON comes back pretty, minified or one object per line. Nothing leaves your machine.
Need to reshape the result rather than read it? Open the app
Why a config file ends up as JSON
Almost nobody converts YAML to JSON because they prefer reading JSON. They do it because a tool on the other side only speaks JSON. Four jobs cover most of it:
- Validating a manifest against a schema. JSON Schema tooling is mature and everywhere. YAML schema tooling is thinner.
- Querying with jq. Every image tag in a compose file is a one-line expression once the file is JSON.
- Diffing two releases. YAML lets the same structure be written several ways, so textual diffs are noisy. Pretty JSON normalises the formatting and leaves the real changes.
- Feeding an API or a template. Request bodies, Terraform variable files and most template engines want JSON.
Worked example: a compose file that leans on anchors
Shared blocks are house style in compose files and CI configs, because repeating six lines of logging settings per service is how they drift apart. Here is one, with an anchor named defaults and two services pulling it in:
x-defaults: &defaults
restart: unless-stopped
logging:
driver: json-file
environment:
TZ: Etc/UTC
services:
api:
<<: *defaults
image: registry.example.com/billing-api:2.4.1
ports:
- "8080:8080"
worker:
<<: *defaults
image: registry.example.com/billing-worker:2.4.1
replicas: 3
And the JSON, exactly as the converter writes it on the default settings:
{
"x-defaults": {
"restart": "unless-stopped",
"logging": {
"driver": "json-file"
},
"environment": {
"TZ": "Etc/UTC"
}
},
"services": {
"api": {
"restart": "unless-stopped",
"logging": {
"driver": "json-file"
},
"environment": {
"TZ": "Etc/UTC"
},
"image": "registry.example.com/billing-api:2.4.1",
"ports": [
"8080:8080"
]
},
"worker": {
"restart": "unless-stopped",
"logging": {
"driver": "json-file"
},
"environment": {
"TZ": "Etc/UTC"
},
"image": "registry.example.com/billing-worker:2.4.1",
"replicas": 3
}
}
}
The merge key is gone and both services carry the full settings. That is the point. JSON has no anchors, so a converter that left << alone hands you an object with a key spelled << and the defaults hanging off it, which no downstream tool understands. Plenty do exactly that, because the merge tag is an optional extra in the YAML 1.2 core schema.
Override order follows the merge specification. Had worker declared its own restart: always, that value would win and the merged one would be dropped.
Dates come out as dates, not timestamps
This is the difference I would check first in any YAML converter. YAML 1.1 defined a timestamp tag, so created: 2024-11-03 loaded as a date object, and writing that object back out gives whatever the writer feels like: an ISO timestamp in a timezone nobody specified, an epoch number, occasionally [object Object]. The reader here uses the YAML 1.2 core schema, which has no timestamp tag, so the value stays "2024-11-03", character for character.
The core schema settles the other YAML 1.1 traps in your favour too. An unquoted no stays the string "no" rather than becoming false, and so do yes, on and off. A value like 12:30 stays a string instead of being read as sexagesimal. Only lowercase true and false are booleans.
Pretty, minified, or one object per line
- Pretty is two-space indentation, for reading a manifest, committing the JSON, or diffing two of them.
- Minified is one line, for a request body or an environment variable. A two-key file becomes
{"a":1,"b":"two"}. - JSON Lines only makes sense when the YAML is a list. A sequence of two maps becomes two compact lines and the download is named
.jsonl. - Try an example loads a Kubernetes ConfigMap carrying a date, a quoted region code and a nested list.
Gotchas worth knowing
- Several documents become an array. A file with
---separators gives one entry per document, plus a note saying how many there were. - Duplicate keys are refused, not silently merged. Two
namekeys in one mapping produce Line 3: duplicated mapping key. Some parsers keep the last and say nothing, which is how a config change lands in staging and is ignored in production. - Unquoted leading zeros are numbers.
zip: 01730loads as1730, because the core schema reads it as an ordinary integer. Quoting it in the source fixes it, and1.10is the same trap. - Infinity and not-a-number become null.
.infand.nanhave no JSON equivalent, so they land asnull. - Tabs are a syntax error. YAML forbids them in indentation and the message names the line.
- Files up to 100 MB, no row cap, no daily quota. Alias references are capped at ten thousand per file, so a runaway config errors instead of wedging the tab.
Frequently Asked Questions
Does it resolve anchors, aliases and merge keys?
Yes, all three. An alias is replaced by whatever its anchor held, and a merge key writes the anchored block's keys into the map that pulled it in. Keys a map declares for itself win over merged ones.
Is my YAML uploaded anywhere?
No. The parser is JavaScript running in your tab, with no upload endpoint behind this page. That matters here, because config files hold hostnames, bucket names and internal service topology. Nothing is kept between visits.
What happens to dates and timestamps?
They stay strings. A line reading created: 2024-11-03 becomes "2024-11-03", character for character. YAML 1.1 had a timestamp tag that turned those into date objects, and every way of writing one back out changes what the file said.
My file has several documents separated by three dashes. What do I get?
One JSON array with one entry per document, plus a note saying how many there were. A single document converts unwrapped, to the value itself. A bundle holding a Service, a Deployment and an Ingress becomes three objects.
Why did my version number 1.10 come out as 1.1?
Because unquoted, 1.10 is a number in YAML, and 1.10 and 1.1 are the same number. Quote it in the source and it stays the string "1.10". Leading zeros are the same trap: 01730 loads as 1730.
It refused my file and named a line. What does that mean?
The file is not valid YAML and the number is the line to open. Duplicate keys report as "Line 3: duplicated mapping key", which matters because a duplicate silently loses data in some parsers. Tabs in indentation report the same way.
Related
Convert your YAML to JSON
No sign-up, no upload, no row cap. Anchors resolved, dates left alone, output copied or downloaded in one click.
Back to the converter