Skip to main content

JSON to YAML, and Back Again: A Practical Guide for Config Files

Convert JSON to YAML and back without losing types or readability. Indentation, quoting gotchas, why YAML wins for configs, and keeping secrets local.

Published By Li Lei
#json #yaml #config #devops #converters

JSON to YAML, and Back Again: A Practical Guide for Config Files

JSON is what machines hand each other. YAML is what people edit at 11pm before a deploy. Most of the config work I do lives in that gap: an API returns JSON, but the file I have to commit is a Kubernetes manifest, a GitHub Actions workflow, or a docker-compose override — all YAML. So I convert, and I convert back. This guide is about doing that cleanly: what actually changes between the two formats, the quoting traps that bite people, and why you should keep the whole thing in your browser when the payload has a password in it.

What Actually Changes Between JSON and YAML

The two formats describe the same data model — maps, lists, strings, numbers, booleans, null — so a conversion is a re-rendering, not a translation. But the rendering rules are different enough to surprise you.

Here is the concrete part worth memorizing:

  • JSON braces and brackets become indentation. A { opening an object and the matching } closing it both disappear. Nesting that JSON shows with punctuation, YAML shows with two more spaces of indent.
  • Keys lose their quotes. "replicas": 3 in JSON becomes replicas: 3 in YAML. The quotes were mandatory in JSON and are noise in YAML, so they go.
  • Arrays become dashed lists. A JSON array ["a", "b"] turns into two lines, each starting with - . Block style, one item per line, no surrounding brackets.

That is the whole visual shift. Everything else — keeping true a boolean, keeping 42 a number — is the converter's job to preserve, and it is exactly where things quietly go wrong if you do it by hand.

A Worked Example

Take this small JSON object — a typical service config snippet:

{
  "name": "billing-api",
  "replicas": 3,
  "debug": false,
  "ports": [8080, 8443],
  "note": "restart at 3:30 PM"
}

Run it through the JSON to YAML converter and you get:

name: billing-api
replicas: 3
debug: false
ports:
  - 8080
  - 8443
note: "restart at 3:30 PM"

Read it line by line and every rule above is visible. The outer braces are gone. "name" shed its quotes and became name. The ports array unrolled into a dashed list, indented under its key. replicas stayed the integer 3, not the string "3". And note kept its quotes — because 3:30 PM contains a colon followed by a space, which YAML would otherwise read as a nested key/value split. That last one is the single most common way a hand-written conversion breaks, and it is the reason a good converter quotes ambiguous strings for you.

The Quoting and Indentation Gotchas

YAML's friendliness comes from how much it infers, and inference is exactly what bites you.

Colon-space inside a value. note: 3:30 PM looks fine until a parser treats the 3: as a key. Anything with a : in the value needs quoting. Same story for values starting with # (read as a comment), - (read as a list item), or ?, @, and a few other indicator characters.

Strings that look like other types. A ZIP code "02118" must stay quoted or YAML may strip the leading zero and hand you the number 2118. A version "1.20" can collapse to 1.2. And the classic: the word yes. Under the older YAML 1.1 rules, yes/no/on/off parse as booleans — which is how a country code or a survey answer silently becomes true. Modern YAML 1.2 keeps them as plain strings, but plenty of parsers in the wild are still 1.1, so when the intent matters, quote it.

Indentation is structure, and tabs are illegal. YAML uses spaces only — a literal tab character in indentation is a spec violation that throws a parse error. Pick a width and stay consistent. Kubernetes, GitHub Actions, and docker-compose all conventionally use 2 spaces; reach for 4 only when the destination file already uses it. Mixing widths inside one file is the fastest route to a confusing parse failure.

Multiline strings. This is where YAML genuinely beats JSON. A shell script embedded in JSON is one long line stuffed with \n escapes. In YAML it becomes a literal block scalar — the |- form — where the text reads as real lines. If you are moving a run: step or an inline certificate, this alone is worth the conversion.

Why YAML for Configs

If JSON already works, why bother? Two reasons that matter for files humans touch.

Comments. JSON has no comment syntax — none. You cannot annotate why replicas is 3 and not 5, or leave a # TODO: bump after Q3 next to a value. YAML's # comments let the config explain itself, which is most of what makes a long config file maintainable. One caveat that trips people up: JSON has no comments to carry over, so converting JSON to YAML never produces comments. You add them by hand afterward; the tool will not invent them.

Readability. Less punctuation, real indentation, dashed lists, and block scalars all add up to a file you can scan. A 200-line Kubernetes manifest in JSON is a wall of braces; in YAML it is something you can review in a PR without squinting.

And the round trip matters too. YAML is great for editing, JSON is great for tooling and APIs, so I move between them constantly — edit the YAML, then push it back through YAML to JSON when a script or an API expects strict JSON. As long as the converter preserves types in both directions, the data survives the trip unchanged.

Keep Secrets Local

Here is the part I care about most, because config files are where credentials live. The first time I needed to turn a curl response into a ConfigMap entry, the JSON had a live database password sitting in it. Pasting that into a random online converter means shipping your secret to someone else's server and into their logs. So I built and use a converter that does the work in plain JavaScript inside the browser tab — JSON.parse plus a YAML stringifier, nothing leaving the page, no analytics recording what you convert, the download built locally from an in-memory blob.

That client-side guarantee is the whole point for anything touching real credentials: an API key, a private key, a Kubernetes secret, a .env value. The conversion happens on your machine and stays there. One honest caveat — the shareable-link feature mirrors your input into the URL so you can send a colleague the exact conversion. That is handy for harmless snippets and a bad idea for secrets, because URLs land in browser history and access logs. When the payload is sensitive, copy the YAML output directly instead of sharing the link, and clear the input when you are done.

A converter that runs locally, preserves your types, quotes the ambiguous strings, and never phones home turns a finicky manual chore into a paste-and-copy. That is the bar for trusting any tool with a config file.


Made by Toolora · Updated 2026-06-13