APIs speak JSON; Kubernetes, GitHub Actions, Ansible, and docker-compose ask for YAML. The translation between them is routine — and routinely done badly, by tools that rewrite text instead of parsing data. Here's what a correct conversion actually does, and the small set of surprises worth knowing before you paste.
Because JSON and YAML share a data model but not a syntax, and the mismatches live exactly where regexes fail. The safe path is always two steps: parse the JSON into real values, then serialize those values as YAML. Parsing resolves escapes, numbers, and nesting once; serialization makes every quoting decision with full knowledge of the value. A worked example from our converter: a 397-byte JSON service config — nested metrics object, two-port array, an environments list — parses and serializes into 274 bytes of YAML over 16 lines, and parsing that YAML back yields a value exactly equal to the original. That round-trip check is the difference between "looks converted" and "is converted."
| JSON | YAML | Gotcha |
|---|---|---|
3.14, 42, -7 | 3.14, 42, -7 | Exponents renormalize: 1e21 → 1e+21 |
true / false | true / false | YAML 1.1 also accepted yes/no — don't use them |
null | null | ~ is legal shorthand; explicit null is clearer |
"a: b" | "a: b" | Quoted: colon-space means "key" in YAML |
"" | "" | An empty plain scalar would read as null |
"multi\nline" | |- block | Readable replacement for \n escapes |
["a","b"] | - a lines | Block sequences by default, not flow [a, b] |
{"a":{"b":1}} | indented keys | Nesting depth = indent level |
The quoting row deserves its own paragraph, because it's the one that surprises people. A YAML serializer quotes strings only when a plain scalar would be ambiguous — the string "42" must be quoted or it becomes the number 42, and "a: b" must be quoted because colon-space is the key separator. But "true story" stays unquoted: read as a whole, it can't be confused with the boolean. That minimal-quoting behavior is a feature — it's why YAML configs read cleaner than their JSON equivalents — and it's also why hand-editing converted files occasionally breaks them: delete one quote pair around a numeric-looking string and you've silently changed its type.
"Every JSON document is a YAML document" is true enough to be useful and false enough to bite. Three concrete gaps: duplicate keys — JSON tolerates {"a":1,"a":2} (last wins in most parsers), while YAML rejects them outright ("Map keys must be unique"); tabs — JSON allows tab whitespace anywhere, YAML forbids tabs as indentation, which makes tab-indented JSON a landmine when pasted into a YAML file and edited; and BOMs — a UTF-8 byte-order mark that many JSON tools emit or tolerate can fail a strict YAML parser at byte zero. Going JSON → YAML through a real parser sidesteps all three; going the other direction is where you'll meet them, as parse errors with line and column attached.
Two dials matter, and ecosystems have opinions. Indent: 2 spaces is the Kubernetes, GitHub Actions, and docker-compose norm; 4 spaces shows up in older OpenStack-era configs and some house styles. Line folding: by default good serializers wrap plain scalars at column 80 (with a continuation indent) to keep diffs reviewable — but some strict pipelines reject folded lines, so converters expose folding as an option. Turn it off when a value must stay on one physical line. Neither choice affects the data; both affect every human who reads the file afterward.
The reverse direction is the same two steps mirrored: parse YAML, serialize JSON. It doubles as the most honest YAML validator — if the file parses and the JSON you get back matches what you expected, the YAML is well-formed — and it surfaces the two classic hand-editing errors with precise locations: tabs as indentation, and duplicate keys. Both produce the engine's error with a line number, column, and a caret under the offending character, which beats "invalid YAML" by a mile when the file is 400 lines of someone else's Helm chart.
Sometimes no, and it's worth saying out loud. JSON is valid input to most YAML parsers — Kubernetes accepts JSON manifests, and docker-compose.json is unusual but legal. Convert when humans will read and edit the file (YAML wins on comments — JSON has none — and readability); keep JSON when machines are the only audience and you want strictness (no comments, no anchors, no ambiguity). And whatever the direction, do it locally if the content is sensitive: config files carry credentials more often than anyone admits.
Paste JSON, get clean YAML — or switch directions and validate by round trip. The yaml engine runs in your browser; nothing is uploaded.
JSON to YAML Converter →Parse, then serialize — never regex. Trust output that proves itself with a round trip, quote only what's ambiguous, and match your ecosystem's indent and folding conventions. Our JSON to YAML converter does all of it bidirectionally in the browser; for adjacent jobs there's the YAML Validator to check existing files and the JSON Formatter to clean up the JSON side first.