YAML to JSON Converter_
Convert YAML to JSON and see exactly what the conversion cost. JSON cannot express comments, anchors, sets, ordered maps, binary values or multi-document streams — so every converter loses some of them, and this one tells you which, on your document, before you copy anything.
Free, no account, and the file never leaves the page.
What this conversion cost
How to use
- 01Start with a document — type into the left pane, or pick a .yaml off disk with Upload. Reading happens here in the tab.
- 02Read the report above the JSON first. That is the part other converters leave out: it names every construct in your document that JSON cannot hold, and what happened to it.
- 03Choose pretty or minified, and an indent. Minified is what you want when the JSON is going into a request body rather than a file.
- 04If the file has several documents, decide how to convert YAML to JSON for a stream — an array keeps all of them, first-only keeps one, and either way the count is reported.
- 05Take the JSON with Copy, or save it as converted.json. Then hold on to the YAML — nothing in the output can rebuild the comments or the references, so this direction only runs once.
YAML constructs with no JSON equivalent
| YAML | What it becomes here | What to do about it |
|---|---|---|
# a comment | Nothing — dropped | Keep the YAML as the source of truth. The JSON is a build artefact |
&anchor / *alias | The alias is replaced by a full copy of the anchored value | Expect the JSON to be larger. Nothing is lost, but the sharing is |
<<: *base (merge key) | Resolved into the mapping | Nothing — this is what you wanted. Leaving it would emit a literal "<<" key |
--- (multi-document) | An array of documents, or the first only | Pick deliberately. A converter that silently takes the first has eaten the rest |
1: or true: as a key | The string "1" / "true" | Usually harmless. Watch for a bare null: key, which becomes the empty string "" |
!!timestamp | An ISO 8601 string | The consumer has to parse it again. There is no JSON date type to target |
!!set | An array of the members | Duplicates are no longer rejected by the format. Enforce that in your code |
!!omap | An object, in insertion order | JSON does not guarantee key order. If order matters, use an array of pairs |
!!binary | The base64 string that was in the YAML | Decode it on the far side. It was base64 in the source too |
!MyTag (custom tag) | The tag is dropped, the value kept | Whatever the tag meant to your loader is gone. Encode it as a field instead |
.inf / .nan | null | JSON has no literal for either, and null means something else entirely |
| and > block scalars | An ordinary string with \n escapes | Nothing — the content survives, only the authoring style is lost |
Everything in this table is reported on your own document in the panel above the JSON, with counts and the actual values, so you never have to work out which rows applied.
Values that change meaning as they cross
| YAML input | JSON output here | The trap |
|---|---|---|
region: NO | {"region": "NO"} | Correct under YAML 1.2. But a 1.1 reader — Kubernetes, Ansible — reads the YAML as false, so the JSON and the YAML disagree about what the file said |
enabled: yes | {"enabled": "yes"} | Same. If your JSON consumer expected a boolean, quote nothing and fix the schema instead |
start: 12:30 | {"start": "12:30"} | Under YAML 1.1 this is 750 — read as base-60. Two readers, two values |
mode: 0755 | {"mode": 755} | The leading zero is dropped, so a file mode becomes the wrong number. Under 1.1 it would have been 493. Quote it in the YAML |
version: 1.10 | {"version": 1.1} | A number, so the trailing zero is gone. Version strings should always be quoted |
id: 9007199254740993 | {"id": 9007199254740992} | Past JSON’s safe integer range. Snowflake and database IDs live here — quote them to keep them exact |
The first three rows are not this converter changing anything: YAML 1.2 already read them as strings. They are here because the JSON makes the disagreement visible for the first time, and because the tool that reads your YAML may not be the one that reads your JSON.
Where this conversion catches people out
The comments are gone and cannot be recovered
JSON has no comment syntax, so every # line in the source vanishes and there is nothing in the output to reconstruct them from. This matters most when somebody treats the JSON as the new source and deletes the YAML — the explanations for every setting go with it. Convert as a build step, keep the YAML in the repository.
Anchors expand, so the file can grow a lot
An anchor defines a block once and an alias points at it. JSON cannot point, so each alias becomes a full copy. A large OpenAPI spec that shares a schema fragment across thirty endpoints produces thirty copies of it. The output is correct and the file can be several times the size of the input — which is a surprise if you are about to put it in a request body.
A stream of documents has no single JSON form
One YAML file, several --- separated documents, is normal in Kubernetes. JSON documents are single values, so a converter has to choose, and taking the first silently is the common choice. The result is valid JSON that looks right and is missing most of your resources.
Duplicate keys resolve without complaint
A mapping that names the same key twice is not an error in YAML — the later value simply wins. By the time the JSON exists there is one value and nothing at all to indicate a second ever existed, so the loss is invisible on the far side. Badly resolved merge conflicts are the usual source: both versions of a block survive the merge, one of them takes effect, and the reviewer sees a diff that looks complete. The report names the key and the line so you catch it here instead.
Timestamps become strings, so the type is gone
A !!timestamp carries the information that a value is a moment in time. JSON has no date type, so it becomes an ISO 8601 string and that knowledge now lives only in whatever code reads it. Schema validators that checked the type will no longer catch a malformed date.
Kubernetes manifests pasted into server-side converters
Think about what actually gets converted: a Deployment on its way into a pipeline, an Ansible inventory, a Secret whose base64 is encoding and not encryption. Those carry live registry credentials and deploy tokens. A converter offering to fetch your document from a URL is doing that fetch on its own machine, and one offering a shareable result link is publishing what you gave it. Neither is hypothetical, and neither is obvious from the button.
When you would reach for it
Feeding an API spec to a generator
An OpenAPI document authored in YAML, consumed by a code generator that only takes JSON. The anchors expand, which is fine, and the report tells you how many so the size change is not a mystery.
paths:
/a: &ep
get: {summary: one}
/b: *ep{"paths":{"/a":{"get":{"summary":"one"}},
"/b":{"get":{"summary":"one"}}}}Putting a manifest through jq
You want to query a Kubernetes file with jq, which does not read YAML. The stream becomes an array, so every resource is still there to select from.
kind: Deployment --- kind: Service
[{"kind":"Deployment"},{"kind":"Service"}]Checking what a config really says
A value is behaving oddly and you want to see what a parser actually makes of it, with no YAML subtleties in the way.
debug: off mode: 0755
{"debug": "off", "mode": 755}Getting this right
- Treat the JSON as an output, not a source. Anything you would have written a comment about belongs in the YAML, and the YAML is what should be in version control.
- Quote anything whose exact characters matter before converting: version strings, file modes, country codes, large IDs, times. A quoted value crosses unchanged.
- If the JSON comes out surprisingly large, check the alias count in the report. That is almost always the reason, and it is not a bug.
- Need to tidy the YAML rather than convert it? The YAML formatter re-indents and validates while keeping the comments and anchors this page has to drop.
- To inspect or re-indent the JSON afterwards, the JSON formatter validates it and flags duplicate keys and unsafe integers. For transport, the Minified option here already gives you the stripped form.
Technical details
- Engine
- Parsing is the same audited YAML reader the formatter uses — one dependency, fetched only when a YAML page is open. Serialisation is this tool’s own, because the standard one loses collections
- Version
- YAML 1.2, core schema. Merge keys are resolved, because JSON has no
<<and leaving one would emit a literal key no consumer expects - Reported
- Comments, expanded aliases, document count, non-string keys, timestamps, sets, ordered maps, binary, duplicate keys, integers past the safe range,
.inf/.nanand dropped custom tags — each on your own document, above the output - Not silently mangled
!!setbecomes an array and!!omapan object, rather than the empty object a plain serialiser produces;!!binarybecomes its base64 string rather than a byte-array wrapper- File handling
- Uploads are read inside the page with the browser File API and are never transmitted; Download writes out what is already in the tab.
- Limits
- Input is refused above 1 MB, checked before any parsing — a tenth of what the JSON tools allow, because a YAML document tree carries layout for every node and costs far more to build than plain text. The output pane stops drawing past 300,000 characters. Copy and Download are unaffected and always carry the complete result.
- Network
- None from tool code. A test sweep calls every function this page uses with
fetchandXMLHttpRequestreplaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.
Frequently asked questions
Can I convert the JSON back to YAML afterwards?
You can get the data back, but not the document. The comments are not in the JSON, the aliases have already been expanded into copies, and a multi-document stream has become an array — none of that can be reconstructed from the output. So a round trip preserves what your program reads and loses what a person reads. Keep the YAML.
Why did my file get so much bigger?
Almost always anchors. An alias in YAML is a reference to a block defined once; JSON has no references, so each one becomes a full copy of that block. A spec that shares a fragment across thirty endpoints ends up with thirty copies. The report above the JSON gives the alias count so you can confirm that is what happened.
What happens to a file with several --- documents?
By default all of them are converted and emitted as a JSON array, with the count reported. You can switch to first-document-only if that is what your consumer wants. What this will not do is silently keep one and drop the rest, which is the common behaviour and the reason a Kubernetes file can arrive at the far end missing most of its resources.
Is my YAML uploaded anywhere?
No — and this is worth asking about a converter specifically, because the things people convert are manifests and CI files with credentials in them. The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on.
What happened to my !!set — the JSON shows an array?
That is deliberate, and it is the case worth knowing about. A !!set parses into a set object, which JSON.stringify does not know how to serialise: rather than complaining it emits an empty object, so a set with five members arrives as {} with everything gone. An array is the only faithful JSON shape for it. The trade is that JSON arrays permit duplicates, so the uniqueness that the set guaranteed is now something your code has to enforce.
Why is a mapping key showing as an empty string?
Because the YAML had a bare null: as a key. JSON object keys are always strings, so every non-string key gets stringified — 1 becomes "1", true becomes "true", and null becomes the empty string "", which is the one that surprises people. The report lists every key this applied to with its line, so you can decide whether the JSON is still saying what you meant.
How do I convert YAML to JSON in Python?
json.dumps(yaml.safe_load(text)) is the whole thing. Use safe_load rather than load: the unsafe variant can construct arbitrary Python objects from tags in the document, so parsing a file you did not write becomes running code you did not write. For multi-document files, yaml.safe_load_all returns a generator of documents.
My YAML had "yes" and the JSON says "yes" rather than true — is that a bug?
No, that is YAML 1.2 doing the right thing. In YAML 1.1 the bare word yes is the boolean true, which is the family of bugs the Norway problem belongs to; 1.2 made it a string. The catch is that Kubernetes and Ansible still read 1.1, so the same file can mean different things to different readers. If your consumer wants a boolean, write true.
Converting YAML to JSON is a one-way trip
Every JSON document is already valid YAML — that is a deliberate property of the YAML specification, and it is why pasting JSON in here converts cleanly rather than erroring. The reverse is not true, and not by a small margin. YAML has comments, references, several key types, an extensible tag system and the ability to hold several documents in one file. JSON has objects, arrays, strings, numbers, booleans and null. Going this direction always runs downhill.
So the interesting question about a YAML to JSON converter is not whether it works. Nearly all of them work, because the conversion is two library calls. The question is what it does with the parts that have nowhere to go, and whether it mentions them. Most say nothing. The panel above the JSON on this page lists, for your actual document, every construct that changed on the way through — how many comments went, which aliases were expanded, what a timestamp became — because deciding whether a lossy conversion is acceptable requires knowing which losses happened.
The two failures that eat data silently
The obvious way to build this tool is to parse the YAML into an ordinary data structure and hand that structure to JSON.stringify. It is two lines and it looks correct. It also has a hole big enough to lose an entire collection through.
YAML's !!set tag parses into a set object, and YAML's !!omap parses into an ordered-map object. Neither is something JSON.stringify knows how to serialise, and rather than complaining it renders both as {} — an empty object, with every member gone and nothing to indicate anything was ever there. A three-line set becomes two characters. Binary values fare differently but no better: !!binary becomes a byte-array wrapper that no consumer expects. This page converts sets to arrays, ordered maps to objects and binary to the base64 string it already was in the source, and reports each one.
Several documents, one JSON file
The asymmetry here is on the JSON side: a JSON document is exactly one value, with no way to express "and then another one". YAML has no such restriction, and a manifest holding a Deployment, a Service and a ConfigMap in one file is entirely ordinary. So a converter is forced into a choice that has no correct answer, and the usual one is to take whichever document came first and mention nothing. Several tools admit this in their documentation; more simply do it. What comes back is valid JSON that resembles your file closely enough to pass a glance, and the missing resources only surface at apply time.
The default here is an array of documents, which is at least lossless, with the count reported. If you genuinely want only the first, the control is there and it still tells you what it skipped. What it will not do is quietly pick one.
What an anchor costs on the way across
An anchor and an alias are YAML's way of saying "this block, again". Define a set of defaults once, mark it with &defaults, and refer to it with *defaults wherever it applies. It keeps a long file honest, because there is one place to change a shared value rather than eleven. JSON has no mechanism for a reference of any kind — every value in a JSON document stands alone — so the only faithful thing a converter can do is write the referenced block out in full at every point it was used.
The data is intact, which is why this counts as a faithful conversion rather than a lossy one in the usual sense. What is gone is the structure: the JSON no longer records that those eleven blocks were ever the same block, so an editor working on the JSON has eleven places to change and no hint that they belong together. It is also a size event. A document that leaned on an anchor heavily can come out several times larger than it went in, which matters if the destination is a request body rather than a file. The report counts the aliases so that the size change is explained rather than mysterious.
Why the report sits above the output
Placement is a design decision here rather than an accident. A warning underneath the thing it warns about is read after the decision it was meant to inform, and a warning behind a disclosure triangle is read by almost nobody. Since the entire argument for this page over a thinner one is that it tells you what changed, hiding that behind a click would be self-defeating.
So the report is inside the output column, between the Copy button and the JSON it describes, it opens itself whenever it has something to say, and it stays quiet when it does not — a document of plain mappings, sequences, strings and numbers converts with nothing lost at all, and in that case no panel appears. When one does appear it is specific: not "this conversion may lose information" but "3 comments were dropped", "2 alias references were expanded", "an integer past the safe range lost precision, and here is what it became". A generic caveat teaches nobody anything, because it is equally true of every document and therefore tells you nothing about yours.
The OpenAPI case
A common reason to convert is an OpenAPI specification: written in YAML because it is more pleasant to author, consumed by a code generator or validator that wants JSON. OpenAPI documents are worth calling out because they are exactly where the lossy parts bite. Large specs use anchors heavily to share schema fragments, and expanding them can make the JSON considerably larger than the YAML — the same fragment repeated at every reference rather than defined once. That is correct output, and it is also a size surprise, so the report tells you how many aliases were expanded.
Doing it in Python or at the command line
For a YAML to JSON conversion in Python, the whole job is json.dumps(yaml.safe_load(text)). The important detail is safe_load rather than load: plain yaml.load can construct arbitrary Python objects from tags in the document, which turns parsing an untrusted file into running its code. Use safe_load unless you specifically need custom tags and control where the file came from. At the command line, yq -o=json . reads a file and prints JSON, and handles multi-document streams by emitting one JSON document per YAML document, which is a third answer to the question above and a perfectly good one for a pipeline. Neither route sends the document anywhere, which is the instinct worth having about a manifest that carries credentials.