Skip to main content
Back to BlogConverter Guides

How to Convert JSON to YAML (and Why Your Key Order Won't Survive)

Convert JSON to YAML in the browser, then learn the four things js-yaml decides for you — key reordering, anchor inlining, line folding, and the big-integer precision trap.

The Toolbox TeamAugust 14, 20267 min read

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 \n becomes 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": "") becomes note: '', not note: (which would be null). They're different types; the dumper gets it right, but don't "clean up" the quotes.
  • sortKeys is 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 (noRefs is 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.