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.

toolkit.codes/yaml-to-json
JSON
Nothing to convert yet

How to use

  1. 01Start with a document — type into the left pane, or pick a .yaml off disk with Upload. Reading happens here in the tab.
  2. 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.
  3. 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.
  4. 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.
  5. 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

YAMLWhat it becomes hereWhat to do about it
# a commentNothing — droppedKeep the YAML as the source of truth. The JSON is a build artefact
&anchor / *aliasThe alias is replaced by a full copy of the anchored valueExpect the JSON to be larger. Nothing is lost, but the sharing is
<<: *base (merge key)Resolved into the mappingNothing — this is what you wanted. Leaving it would emit a literal "<<" key
--- (multi-document)An array of documents, or the first onlyPick deliberately. A converter that silently takes the first has eaten the rest
1: or true: as a keyThe string "1" / "true"Usually harmless. Watch for a bare null: key, which becomes the empty string ""
!!timestampAn ISO 8601 stringThe consumer has to parse it again. There is no JSON date type to target
!!setAn array of the membersDuplicates are no longer rejected by the format. Enforce that in your code
!!omapAn object, in insertion orderJSON does not guarantee key order. If order matters, use an array of pairs
!!binaryThe base64 string that was in the YAMLDecode it on the far side. It was base64 in the source too
!MyTag (custom tag)The tag is dropped, the value keptWhatever the tag meant to your loader is gone. Encode it as a field instead
.inf / .nannullJSON has no literal for either, and null means something else entirely
| and > block scalarsAn ordinary string with \n escapesNothing — 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 inputJSON output hereThe 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.

YAML
paths:
  /a: &ep
    get: {summary: one}
  /b: *ep
JSON
{"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.

YAML
kind: Deployment
---
kind: Service
JSON
[{"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.

YAML
debug: off
mode: 0755
JSON
{"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/.nan and dropped custom tags — each on your own document, above the output
Not silently mangled
!!set becomes an array and !!omap an object, rather than the empty object a plain serialiser produces; !!binary becomes 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 fetch and XMLHttpRequest replaced 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.

UTF-8
Ready
100% LOCAL

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.