YAML ↔ JSON Converter
Convert either way with key order and comments-free fidelity, then see every scalar whose written form and parsed value disagree.
3 scalars that do not mean what they look like
line 6, column 32 — 1.20
“1.20” is a number, so it becomes 1.2 — the trailing zero is gone. Version strings like this need quotes.
line 16, column 22 — no
“no” is a string under YAML 1.2 but a boolean under YAML 1.1 — the Norway problem. Anything still reading 1.1 (including many Ruby and Python loaders) sees false here. Quote it.
line 23, column 26 — 0755
“0755” loses its leading zero: YAML 1.2 reads it as decimal 755, while YAML 1.1 read it as octal. A file mode or a zero-padded id has to be quoted to survive either.
Settings
How YAML ↔ JSON Converter works
JSON has ten or so productions and one way to write anything. YAML has three schemas, two incompatible versions in active use, block and flow styles for every collection, five ways to write a multi-line string, anchors, aliases, merge keys, explicit tags and a document separator. Converting between them is therefore lossless in one direction and lossy in the other: every JSON document is already valid YAML 1.2, while a YAML document may carry structure — comments, anchor names, the choice of block scalar — that JSON has no place to keep.
The interesting failures are not syntax errors, though. They are scalars that parse cleanly into a value other than the one they visibly spell. YAML 1.1 resolved a generous set of unquoted words to booleans: y, yes, on, n, no and off, in several capitalisations. YAML 1.2 dropped all but true and false, so the same file loads as a string in a modern parser and as a boolean in an older one — and plenty of widely used loaders are still 1.1. The country code for Norway, NO, is the standard example, which is why the whole family of bugs carries that name.
The number types have their own version history. YAML 1.1 read a colon-separated literal such as 12:30 as base 60, giving 750, and a leading zero as octal, so a file mode written as 0755 became 493. YAML 1.2 keeps the first as a string and reads the second as the decimal 755 — three different answers to the same four characters, depending only on which loader opens the file. A version number written as 1.20 is worse still, because both versions agree it is the number 1.2 and the trailing zero is simply gone.
The last trap belongs to JSON rather than YAML. A JSON number is a double, so integers above 2⁵³ cannot be represented exactly. Snowflake identifiers, epoch nanoseconds and 64-bit database keys all live above that line, and passing one through JSON silently rounds it — the value that comes out is a valid number that is not the value that went in. Quoting is the fix for every one of these, which is why the scanner on this page reports the position of each scalar that needs it rather than converting quietly around them.
Reference
- YAML 1.1 booleans: y|Y|yes|Yes|YES|n|N|no|No|NO|on|On|ON|off|Off|OFF
- YAML 1.2 core schema booleans: true | false only
- 12:30 → 750 under 1.1 (12 × 60 + 30), "12:30" under 1.2
- 0755 → 493 under 1.1 (octal), 755 under 1.2 (decimal)
- Exact integer range of a JSON number: −(2⁵³ − 1) … 2⁵³ − 1
- Document separator: --- starts one, ... ends one
How to use this converter
Choose the direction
Both directions parse with the same YAML 1.2 engine, but the JSON side is validated strictly first so that unquoted keys and trailing commas are refused rather than quietly accepted.
Paste the document
A whole manifest, a compose file, a pipeline definition — including a multi-document stream, which collapses into a top-level array on the way to JSON.
Read the flagged scalars before the output
Each one is reported with its line, its column and what a different parser would make of it. These are the differences that survive a successful conversion.
Send the output back through to check it
A round trip that returns the document you started with is the strongest evidence available that nothing was lost in between.
Worked examples
The Norway problem
- Given
- country: NO
- Result
- The string "NO" under 1.2, the boolean false under 1.1
A configuration file that behaves differently depending on which library loaded it. Quoting the value makes both versions agree.
A file mode losing its zero
- Given
- mode: 0755
- Result
- 755
Not octal 493 as it would have been under YAML 1.1, and not the string either. Anything zero-padded — modes, account numbers, zip codes — needs quotes.
An identifier past double precision
- Given
- id: 9007199254740993
- Result
- 9007199254740992
Rounded before any conversion happens, because the value cannot be held exactly. The last digit is simply wrong, and nothing in the pipeline reports it.
A merge key resolved
- Given
- defaults: &d {image: nginx}\nweb: {<<: *d, name: web}
- Result
- web contains both image and name
Merge keys are a 1.1 feature that a strict 1.2 reader hands back as a literal "<<" key. Resolving them is what anyone writing a pipeline or compose override actually means.
When to use it
- Turning an API response into a manifest fragment without hand-indenting it.
- Checking why a boolean-looking setting in a pipeline behaves as if it were on when the file says no.
- Flattening a multi-document stream so a script can iterate over it as an array.
- Feeding a YAML config to a tool that only accepts JSON, and getting the errors positioned when it will not parse.
- Reviewing a generated configuration for values that will not survive the next tool in the chain.
Things to watch out for
- Comments do not survive the trip. JSON has no syntax for them, so a converted file loses every one — keep the original if the comments matter.
- Anchors and aliases are resolved into the values they point at, which means a document that repeated a block five times through one anchor comes back with five copies of it.
- Key order is preserved in both directions, deliberately. Sorting is available as a toggle rather than a default, because the order of a manifest is usually a decision somebody made.
- Tabs are not valid indentation anywhere in YAML. An editor set to insert them produces errors that point at the line after the problem.
- A multi-document stream has no JSON equivalent, so it becomes a top-level array; converting back with the split option restores the separators.
Frequently asked questions
Why does my YAML value no become false?
Because YAML 1.1 resolved a whole family of words — no, off, n and their capitalisations — to booleans, and many loaders still implement that version. Wrapping the value in quotes forces it to stay a string under every version.
Is JSON valid YAML?
Under YAML 1.2, yes: the specification was rewritten to make JSON a strict subset, so any JSON document parses as YAML. The reverse does not hold, since YAML adds anchors, comments, multiple documents and unquoted scalars.
What happens to my comments when I convert to JSON?
They are discarded, because JSON has nowhere to put them. This is the one genuinely lossy part of the conversion, and it is why converting a documented config to JSON and back is not a safe way to reformat it.
Why did my large ID change during conversion?
JSON numbers are double-precision floats, exact only up to 2⁵³. An identifier larger than that is rounded to the nearest representable value the moment it is parsed, so it must be quoted as a string to survive intact.
Does converting preserve the order of my keys?
Yes, in both directions. Mappings are carried through as ordered structures rather than plain objects, which also stops numeric-looking keys such as port numbers from being hoisted to the front of a mapping.
Why is my 1.20 version string showing as 1.2?
Unquoted, it is read as a number, and the trailing zero of a number carries no information. Both YAML versions agree on this one — quoting is the only way to keep the string exactly as written.
Related DevOps tools
All devops tools- .env File Converter Parse a dotenv file the way real readers do — quoting, escapes, comments — and retype it as JSON, YAML, docker flags, Compose, a Secret or a ConfigMap.
- htpasswd Generator Build Apache basic-auth lines with bcrypt, $apr1$, {SHA} or plain text, verify an existing hash, and collect several users into one file.
- Cron Expression Parser Read a cron line in plain English, expand every field, and see the next ten firings in local time and UTC.
- CIDR / Subnet Calculator Turn an IPv4 or IPv6 prefix into netmask, broadcast, usable range and host count — then split it, compare it, or aggregate a range.
- chmod / Unix Permissions Calculator Bind permission checkboxes, octal and symbolic modes together — including setuid, setgid, sticky and what a umask leaves behind.
- Uptime & SLA Calculator Convert an availability target into allowed downtime per day, month and year, track the error budget, and chain several services together.