You have a JSON file and the platform wants YAML
Kubernetes manifests, Docker Compose, GitHub Actions, Ansible playbooks — they all want YAML. Your config is JSON, maybe a tsconfig fragment or a chunk of a CloudFormation template you're migrating. The shapes are the same; the syntax is in the way. Paste it into the JSON to YAML Converter, pick an indent, copy the result. That's the whole interaction, and for most configs it's correct on the first try.
The interesting part is what happens when it isn't. The conversion runs through js-yaml's dumper, and that dumper makes four decisions for you — three of them good, one of them a silent data-corruption trap. Knowing which is which is the difference between a config that round-trips and one that breaks at 2 a.m.
What the dumper already gets right
YAML's reputation for danger comes from unquoted scalars that change type on you — yes becoming a boolean, 2026-01-01 becoming a date, 123 becoming a number. Here's the thing: js-yaml's dumper quotes all of them for you.
reply: 'yes'
flag: 'no'
enabled: 'true'
missing: 'null'
date: '2026-01-01'
num: '123'
at: '@user'
Every one of those was a string in the JSON, and every one stays a string in the YAML, single-quoted so it can't be misread on the way back in. You don't have to think about quoting. The failure mode isn't the converter — it's the human who later edits the output, deletes the quotes around yes because they look ugly, and turns a string into a boolean. Leave the quotes alone.
The four decisions the dumper makes for you
1. Your key order changes
This is the one nobody expects. JSON objects are unordered by spec, but JSON.parse in V8 preserves insertion order — with one exception: keys that look like integers get hoisted to the front, sorted numerically.
Input JSON:
{ "name": "web", "2": "replicas", "port": 8080, "1": "ready" }
Output YAML:
'1': ready
'2': replicas
name: web
port: 8080
The integer-like keys jumped to the top. They're quoted (so they stay strings, not numbers — good), but the order you wrote is gone. If a reviewer is diffing against the original JSON, the whole block looks rewritten even though no value changed. For stable, alphabetical order, flip Sort keys on. For your original order back on integer-keyed data — you can't get it through this path. The reordering happens at JSON.parse, before the dumper ever runs.
2. Repeated objects get inlined, not anchored
A JSON document with the same object referenced twice — say, a shared labels block used in two containers — would, by default, come out of js-yaml as:
first: &ref_0
app: web
second: *ref_0
An anchor and an alias. It's valid YAML, it's DRY, and it's a pain in a config file — most editors don't expand it, and kubectl will resolve it but humans reading the diff won't. The tool sets noRefs: true, so the output inlines the duplicate in full:
first:
app: web
second:
app: web
Larger output, but each block stands alone. That's the right default for configs. If you actually want anchors (rare, and only worth it for genuinely shared, large blocks), this tool won't emit them — you'd hand-edit.
3. Line width folds your strings
The default line width is 80. A long string gets wrapped into a folded block scalar:
description: >-
This is a fairly long string that should exceed the default line width of
eighty characters and therefore get folded by the dumper into multiple lines
of output.
The >- means folded (newlines become spaces) and strip (no trailing newline). It's valid, but it's a diff hazard: edit one word and the whole block reflows. For anything that lives in git and gets reviewed line-by-line, switch Line width to Unlimited (-1). The same string then stays one line, and a one-word edit is a one-line diff. Save folding for prose; keep config flat.
4. Big integers lose precision before the dumper even runs
This is the trap. JSON numbers parse through JavaScript's Number, a 64-bit float with 53 bits of integer precision. Anything above 2^53 — 9,007,199,254,740,992 — can't be represented exactly.
{ "id": 9007199254740993, "txn": 12345678901234567890 }
Comes out:
id: 9007199254740992
txn: 12345678901234567000
The last digits are wrong. The ...993 became ...992; the ...890 became ...000. This isn't a YAML problem — it's already corrupted the instant JSON.parse runs, and the dumper faithfully writes the corrupted number. Snowflake IDs, credit-card numbers, large primary keys, BigInt columns: all silently rounded. If your JSON carries an identifier that big, it has to be a string in the JSON ("id": "9007199254740993"), not a number. No converter can save you after the parse.
Gotchas
- Multi-line strings become block scalars. A JSON string with
\nbecomes a|-literal block (newlines preserved, trailing newline stripped). If you need the trailing newline kept, that's|+, and the tool won't emit it — patch it by hand. - Empty string maps to
''. A key with an empty-string value ("note": "") becomesnote: '', notnote:(which would be null). They're different types; the dumper gets it right, but don't "clean up" the quotes. sortKeysis alphabetical, not natural. It sorts as strings, so'2'comes before'port'(digits before letters in ASCII), not in any numeric-ish order. Fine for stable diffs, surprising if you expected otherwise.- The reverse trip isn't free. Converting back with YAML to JSON loses comments and any anchors you added by hand. Keep the JSON as the source of truth if you need round-trips.
Summary
- Paste JSON into the JSON to YAML Converter; the dumper quotes ambiguous strings for you, so don't hand-edit the quotes out.
- Watch for four dumper decisions: key reordering (integer-like keys jump to the top), anchor inlining (
noRefsis on by default), line folding (use Unlimited for git-friendly diffs), and big-integer precision loss (the parse corrupts it before YAML sees it). - Quote any identifier above 2^53 as a string in the JSON first.
- Going the other way: YAML to JSON. For a different shape: JSON to CSV. One converter for both directions: JSON ↔ YAML.