JSON โ YAML Converter
Convert JSON to YAML and YAML to JSON instantly. Perfect for Kubernetes, Docker Compose, GitHub Actions, and API specs โ 100% browser-based.
TL;DR
YAML 1.1 is a superset of JSON โ every valid JSON document is also valid YAML, so JSON โ YAML never loses data. The risk runs the other way. Unquoted YAML scalars get type-guessed, so no becomes the boolean false (the famous "Norway problem"), a version string like 1.20 becomes the number 1.2, and a leading-zero ZIP code can be read as octal. The universal fix is the same every time: wrap the value in quotes. The pitfall table below lists the exact surprising value and the fix for each case.
YAML is a superset of JSON โ why that matters for conversion
Since the YAML 1.2 spec, JSON is officially a subset of YAML. That has one practical consequence: converting JSON to YAML is safe and lossless. Keys, strings, numbers, arrays, and objects map one-to-one, and a JSON-shaped document is still legal YAML if you paste it unchanged.
The danger is the reverse direction. JSON is explicit โ a value is a string only if it is wrapped in double quotes, and a number is always a number. YAML is implicit: an unquotedscalar is handed to a type-resolver that guesses whether you meant a string, a boolean, an integer, a float, a date, or null. Most JSON-to-YAML bugs are really "a string in JSON came back as a different type after a YAML round-trip."
This converter emits valid YAML and quotes ambiguous scalars when it serializes JSON, so the output round-trips cleanly. The pitfalls below matter most when you are hand-writing YAML or reading YAML that someone else wrote without quotes.
YAML type-coercion pitfalls: the value you wrote vs. the value you get
These are the unquoted scalars that bite people. The middle column is what a YAML 1.1 parser (the version PyYAML, Kubernetes, and Ansible behave like) actually resolves the value to. The fix is identical for every row: quote it.
| You wrote (unquoted) | Parser returns | Fix |
|---|---|---|
country: no | boolean false (Norway!) | country: "no" |
answer: yes | boolean true | answer: "yes" |
state: on | boolean true | state: "on" |
toggle: off | boolean false | toggle: "off" |
version: 1.20 | float 1.2 (trailing zero dropped) | version: "1.20" |
tag: 1.10 | float 1.1 | tag: "1.10" |
zip: 07030 | octal int 3608 (YAML 1.1) | zip: "07030" |
pin: 0123 | octal int 83 (YAML 1.1) | pin: "0123" |
scale: 1.2e+5 | float 120000.0 (scientific) | scale: "1.2e+5" |
time: 22:22 | int 1342 (sexagesimal, YAML 1.1) | time: "22:22" |
value: null / ~ | null (not the string) | value: "null" |
empty: (nothing after) | null | empty: "" |
date: 2026-06-07 | a timestamp object, not a string | date: "2026-06-07" |
YAML 1.2 (the version js-yaml defaults to) dropped the octal-with-leading-zero, sexagesimal, and yes/no/on/off boolean rules โ but Kubernetes, Ansible, and most Python tooling still behave like YAML 1.1, so assume the surprising value will happen in production.
Indentation, multiline strings, and anchors โ the structural traps
Spaces only โ never tabs
YAML structure is defined entirely by indentation, and the spec forbids tab characters for indentation. A single tab pasted from another editor produces a parser error that points at the wrong line. If a hand-written YAML file "won't parse" for no visible reason, search for tabs first.
Block scalars: | keeps newlines, > folds them
This is the single most useful YAML feature that JSON lacks. A literal block | preserves every line break; a folded block > joins lines with spaces. Both convert to a JSON string with the appropriate \n characters.
script: | echo "line one" echo "line two" # becomes JSON: # "script": "echo \"line one\"\necho \"line two\"\n"
Add a - (|-) to strip the final newline, or a + (|+) to keep all trailing newlines.
Anchors (&) and aliases (*) get expanded on the way to JSON
YAML lets you define a block once with an anchor and reuse it with an alias. JSON has no such concept, so converting to JSON inlines the value into every place it was referenced โ the DRY-ness is lost but the data is identical.
defaults: &base
retries: 3
prod:
<<: *base
retries: 5
# JSON inlines it: prod = { "retries": 5 }A maliciously nested alias chain is the basis of the "billion laughs" expansion attack โ another reason never to parse untrusted YAML with a full-power loader.
Duplicate keys are silently allowed by some parsers
JSON objects can technically repeat keys (last wins), and several YAML parsers do the same instead of erroring. If two keys collide, the second value overwrites the first with no warning โ a common cause of "my config setting is being ignored."
Feature parity: what survives a JSON โ YAML round-trip
| Feature | JSON | YAML |
|---|---|---|
| Comments | No | Yes (#) โ lost when converting to JSON |
| Multiline strings | Escaped \n only | Block scalars | and > |
| Anchors / reuse | No | Yes โ inlined when converting to JSON |
| Implicit typing | No (types are explicit) | Yes โ the source of every pitfall above |
| Trailing commas | No | N/A (no commas in block style) |
| Whitespace significant | No | Yes โ indentation defines structure |
| Streaming multiple docs | No | Yes (--- separator) |
The two lossy directions: JSON โ YAML drops nothing; YAML โ JSON drops comments and collapses anchors. If comments matter (most Kubernetes manifests rely on them), keep the YAML as the source of truth and treat JSON as a derived artifact.
Questions developers actually ask about JSON and YAML
Why did my YAML value no turn into false?
This is the "Norway problem." In YAML 1.1, the unquoted scalars no, yes, on, off, true, and false are all resolved to booleans before they ever reach your application. The two-letter ISO code for Norway is NO, so a country list written without quotes loses Norway to false. Fix it by quoting the value: country: "no".
Why does my version number 1.20 become 1.2?
An unquoted 1.20 is type-resolved as a float, and floats drop trailing zeros, so it becomes 1.2. Worse, 1.10 sorts below 1.9 numerically. Always quote version strings, image tags, and any "number" you intend to compare as text: version: "1.20".
Is converting JSON to YAML lossless?
Yes. Because JSON is a subset of YAML, every JSON document converts to YAML without losing data or changing types. The reverse (YAML โ JSON) is lossy only for things JSON cannot represent: comments are dropped, and anchors/aliases are expanded inline. The actual key/value data is always preserved.
Why does my YAML fail to parse when JSON with the same data works?
Three usual suspects: (1) a tab character used for indentation โ YAML forbids tabs; (2) inconsistent indentation where sibling keys don't line up at the same column; or (3) a value starting with a special character like {, [, @, %, or : that needs quoting. JSON is brace-delimited so none of these matter there.
How do I write a multi-line string in YAML?
Use a block scalar. | (literal) keeps every newline exactly; > (folded) joins lines with single spaces and preserves blank lines as breaks. Add - to chomp the trailing newline (|-). Converting back to JSON turns the whole thing into one string with embedded \n escapes โ which is why a shell script in a GitHub Actions step uses run: |.
Is my data sent anywhere when I convert it?
No. This site is a static export with no backend, and the conversion runs entirely in your browser's JavaScript engine. You can confirm it in DevTools โ Network: converting triggers zero outbound requests. That said, never paste secrets from a production Kubernetes Secret manifest into any online tool โ strip them first.