Skip to content
Tresna

YAML to JSON Converter

Convert YAML to JSON, or JSON to YAML. Names the schema it used, and reports every value the conversion changed, dropped or rounded — including the ones a YAML 1.1 parser would read differently.

YAML ⇄ JSON

YAML 1.2 core

How to use this tool

YAML is a superset of JSON. That makes the conversion easy and the result untrustworthy in a specific way: YAML can say things JSON cannot, and the parts it cannot say do not fail — they are quietly replaced with something that looks fine.

  1. 1`YAML → JSON` reads a YAML file and writes JSON. `JSON → YAML` does the reverse.
  2. 2Press **Convert**. Nothing is computed until you do, so a large file costs nothing until you ask.
  3. 3Read the list of changes between the input and the output. It appears only when there is something in it, and every entry names the path it happened at.

There are two YAML schemas, and they disagree

This page uses **YAML 1.2, core schema**. That is a choice, and it changes what your file means. YAML 1.1 — the older specification, still what a great deal of deployed configuration tooling implements — reads several very common values differently.

Written asYAML 1.2 (this page)YAML 1.1 (PyYAML)
country: no"no"false
a: yes"yes"true
a: on"on"true
n: 0121210
n: 0755755493
t: 12:30"12:30"750
n: 1_000_000"1_000_000"1000000
a: 1e31000"1e3"
a: 0o1715"0o17"
a: 0b11"0b11"3
d: 2024-01-01"2024-01-01"a date object
What each schema makes of the same file. The 1.1 column is PyYAML's actual output, not a summary of the specification.

The first row is the Norway problem, and it is worth dwelling on because it is a country code that becomes a boolean. Everything else has the same shape: the file is fine, both parsers are correct, and the two disagree about what it says.

Quoting settles it

Every row above is about an *unquoted* value, because that is where a parser has to infer. `'012'`, `"1_000"` and `'no'` are strings under both schemas — the quotes are an instruction, and both parsers follow it. This page does not warn about quoted text, and if you are writing a file that more than one tool will read, quoting is the fix that costs nothing.

The rules behind the table are not what you would guess

Two of these are the kind of detail that is easier to measure than to remember, and this project measured them because the first attempt at writing this table got both wrong:

  • YAML 1.1's float pattern needs a decimal point **and** a signed exponent. `1.5e-3` is a number; `1.5e3` is text; `1e3` is text. Both, not either.
  • The base prefixes run in opposite directions. YAML 1.2 has `0o` and `0x` and no `0b`. YAML 1.1 has `0b` and `0x` and no `0o`.
  • Digit separators exist in 1.1 and not in 1.2's core schema, so `1_000_000` is a number to one and a string to the other.

What the conversion changes without saying so

These are not schema differences. In every case the output is correct JSON, the value has genuinely changed, and nothing in the output indicates it. This is the reason the page shows a list rather than just a result:

Written asIn the JSONWhat happened
value: .nannullA real NaN, which JSON cannot write
value: .infnullA real Infinity, same reason
id: 1234567890123456789012345678901234567000Past 2^53, a number stops being exact
id: 90071992547409939007199254740992Off by one, at the first integer that loses anything
n: 1e-4000Smaller than the number type can hold
null: value""A key of null becomes the empty string
0x1F: value"31"A key of 0x1F becomes a different key
a: !!set{}The set's members are gone; a set has no JSON form
Written in YAML, and what the JSON below says.

The `.nan` case is the sharpest one. JavaScript has a real `NaN`, and `JSON.stringify` writes it as `null` without complaint. The JSON is valid. The value is destroyed. And a reader of the output has no way to tell that null from a null you wrote on purpose.

The boundary, because a check without one is just noise

This page does **not** warn about float precision. `0.1` has no exact binary representation, strictly, so in that sense every float is imprecise, and detecting it honestly would need exact decimal arithmetic that fires on values which round-trip perfectly. So it is not reported.

What *is* reported is the two unambiguous cases: a value that is not finite, and a non-zero literal that became zero. And the integer check has a boundary in both directions — `9007199254740991` is the largest integer a JavaScript number holds exactly and this page says nothing about it, while `9007199254740992` is the next one up and is also exact, and the first that is not is `9007199254740993`.

Going the other way is safer, and still not lossless

JSON to YAML is the comfortable direction, because JSON is a subset of YAML 1.2 — every JSON document is a valid YAML document, and every value keeps its type. The strings that look like other types are quoted on the way out, which is the whole job:

{ "a": "1", "b": "true", "c": "null", "d": "no" }
Four strings that would change type if they were not quoted.

One thing this page does that a `JSON.stringify`-based converter cannot: it keeps your key order. `{"2":"b","1":"a"}` comes out as `2` then `1`, not the other way round.

The reason is worth knowing, because it will bite you somewhere else. JavaScript hoists integer-like keys on **every** object, so `JSON.parse` has already thrown your order away by the time any code sees it. The page reads the source with an order-preserving parser instead — the same one the JSON Formatter uses — and rebuilds the document in the order you wrote it.

Things this page refuses

A converter that cannot fail is not a converter, it is a formatter with opinions. Three refusals, each for the same reason — the alternative is a result that looks right and is not:

  • **A file with more than one document.** A Kubernetes manifest is a `---`-separated document stream, and converting the first and dropping the rest hands back a file that parses and is missing most of its content. The page says how many documents there are and converts none of them.
  • **Duplicate keys.** A YAML 1.1 parser keeps the last value and says nothing, so a file that sets `image:` twice quietly resolves the other way round. This page stops.
  • **A file whose anchors multiply.** Anchors expand exponentially — each level repeats the last by some factor — so a small file can be a denial of service. It is refused, with a message about what happened rather than a claim that you tried to attack it, because almost every file that trips this is somebody's workflow multiplying by accident.

Merge keys are the near miss. A `<<` key is not resolved here: it is left as a literal key called `<<` holding the mapping it pointed at, so a child does not gain its parent's keys. A 1.1 parser would have merged them. The page reports it rather than quietly doing either thing.

On round-tripping

You will see converters advertise that a value survives a round trip. For the JSON-native subset that is very nearly true, and "very nearly" is doing real work in that sentence: the formatting changes, the line endings change, and a comment does not come back at all, because JSON has nowhere to put one.

For anything using YAML's own features it is often simply false. `.nan` does not come back. A `!!set` does not come back. A key of `1` comes back as the string `"1"`. If you need a round trip to be exact, keep the original — which is the advice this page can give without needing to be clever, and the reason it never offers to overwrite anything.

What it runs on

One dependency: the `yaml` package, which has no dependencies of its own. Hand-rolling a YAML parser was never a serious option — the grammar is large, and a partial implementation accepts what it understands and mishandles the rest, which is worse than having none.

The behaviour described on this page was checked against **PyYAML**, an independent YAML 1.1 implementation, in the project's test suite. That is what makes the 1.1 column above a measurement rather than an assertion — and it is what caught three errors in the first draft of this table.

Frequently asked questions

Is my file uploaded anywhere?
No. The conversion runs in this browser tab. There is no server component to this site, so there is nowhere for the file to go.
Which YAML version does this use?
YAML 1.2, core schema. The page says so in the status bar, and it matters: under 1.2, `no` is the string "no", `012` is the number 12, and `2024-01-01` is text. A 1.1 parser reads all three differently, and this page lists every value where that applies to your file.
Will a value survive being converted and converted back?
For plain JSON-shaped data, almost always. For YAML's own features, often not: `.nan` becomes null and stays null, a `!!set` is gone, and a key written as `1` returns as the string "1". The page reports each of these at the moment it happens rather than leaving you to find out later.
Why does it warn about `country: no`?
Because a YAML 1.1 parser reads it as `false`, and a great deal of configuration tooling still uses 1.1. Under 1.2 — which this page uses — it is the string "no". Both readings are correct for their schema, which is exactly what makes it worth telling you about. Quoting it, as `country: "no"`, removes the ambiguity for every parser.
Why is my multi-line YAML file refused?
Because it contains more than one document, and converting only the first would drop the others without saying so. A Kubernetes manifest is the usual case. The page reports how many documents it found — split the file and convert each part.
Does it support YAML anchors and aliases?
Aliases are expanded, which is what you almost always want. A `<<` merge key is **not** resolved: it stays as a literal key called `<<` holding the mapping, and the page says so, because a 1.1 parser would have merged it and the two results differ.
Why does it refuse a file with the same key twice?
Because YAML 1.1 parsers keep the last value silently, so a file that sets a key twice resolves the other way round with nothing to indicate it. Refusing is safer for a file you are about to overwrite.