</>DevTools

Y/JJSON ↔ YAML

Convert between JSON and YAML formats

Converting Between JSON and YAML: What Survives and What Doesn't

YAML is a superset of JSON, so every JSON document is valid YAML and converting JSON → YAML is lossless. The other direction is different: YAML has features with no JSON equivalent, and they quietly disappear or change shape in translation. Whichever way you're converting, that asymmetry is the thing to know.

The same data, two notations

YAML is pleasant to hand-write because quotes, braces, and commas are mostly unnecessary and comments are allowed. That's why human-edited configuration — Kubernetes manifests, GitHub Actions workflows, Docker Compose files — is YAML, while data exchanged between programs is JSON.

JSON
{
  "name": "my-app",
  "version": "1.0.0",
  "ports": [8080, 8443],
  "env": {
    "NODE_ENV": "production",
    "DEBUG": false
  }
}
YAML
name: my-app
version: 1.0.0
ports:
  - 8080
  - 8443
env:
  NODE_ENV: production
  DEBUG: false

How to use it

  1. Paste the JSON or YAML you want to convert.
  2. Choose the conversion direction.
  3. Review the result; invalid input syntax produces an error message.
  4. When converting YAML → JSON, check the loss table below first.

What YAML loses on the way to JSON

Comments hurt the most in practice. Comments in a Kubernetes manifest or CI config often hold knowledge that isn't expressible in the config itself — why a value must not change, for instance — and a round trip through JSON erases all of it. Don't round-trip a config file and overwrite the original.

YAML featureAfter conversion to JSON
# commentsGone entirely
Anchors (&) and aliases (*)Expanded — values duplicated inline
Multiple documents (--- separated)Only the first survives, or an error
Block scalars (| and >)A single string containing \n
Date typesConverted to strings
Non-string keys (numbers, booleans)Coerced to string keys
Tags (!!str and friends)Lost

Anchors and aliases

YAML has syntax for reusing values: define with &name, reference with *name, and merge mappings with <<: *name. Docker Compose and GitLab CI configs use it constantly to declare shared settings once. Converting to JSON expands every reference into the actual value, so the result is correct but duplicated and larger.

Reusing shared config with an anchor
defaults: &defaults
  adapter: postgres
  encoding: utf8

development:
  <<: *defaults
  database: myapp_dev

test:
  <<: *defaults
  database: myapp_test

How YAML's type inference causes outages

YAML infers the type of unquoted values, and that convenience is behind some famous bugs. The best known is the Norway problem: the country code NO, written unquoted, is parsed as the boolean false by YAML 1.1 parsers. For the same reason yes, no, on, off, y, and n all become booleans.

Version numbers are another frequent casualty. version: 1.0 parses as the number 1.0 rather than the string "1.0", while version: 1.0.0 has two dots and stays a string — so the same file becomes inconsistent. Leading-zero numbers like 08 are treated as octal and either error or change value, and time-like notation (12:30) is read as base-60 and becomes 750 in some implementations.

The fix is simple: quote anything that must be a string. Make it a habit for versions, country and language codes, phone numbers, identifiers with leading zeros, and time-like values.

What quoting changes
country: NO        # → false (a boolean!)
country: "NO"      # → "NO"

version: 1.0       # → 1 (a number)
version: "1.0"     # → "1.0"

zip: 08301         # → parsed as octal; error or wrong value
zip: "08301"       # → "08301"

enabled: yes       # → true
enabled: "yes"     # → "yes"

Indentation rules

  • Tabs are forbidden. The YAML spec prohibits them outright, so use spaces — an editor configured to insert tabs produces parse errors that are hard to trace.
  • The indent width is up to you but must be consistent within a level. Two spaces is conventional.
  • A list item's hyphen may sit in the parent's column or be indented one level. Both are valid; pick one per file.
  • A space is required after the colon. key:value parses as a single string.
  • Values containing a colon followed by a space must be quoted.

Which format to choose

SituationUseWhy
API requests and responsesJSONParsers everywhere, no ambiguity
Human-edited configurationYAMLComments and terse syntax
Logs (one record per line)JSON LinesSuits line-based processing and streaming
Build and CI pipeline definitionsYAMLEcosystem standard
Externally published schemasJSONMature validation tooling
Parsing untrusted inputJSONYAML parsers do far more, so the risk surface is larger

Frequently Asked Questions

Is every JSON document valid YAML?
Per the YAML 1.2 spec, yes — 1.2 is defined as a JSON superset, so you can feed JSON straight to a YAML parser. Many implementations still follow YAML 1.1, where a few exceptions exist, so verify with your actual parser if it's on a critical path.
Is key order preserved?
This tool preserves input order. Note though that YAML mappings are specified as unordered, so passing the data through other tools may reorder them. It's best not to build designs that depend on key order.
Is there any way to keep YAML comments?
Not through JSON, which has no comment syntax. If you need to modify YAML programmatically while keeping comments, use a round-trip parser that preserves them — ruamel.yaml in Python, or a YAML AST library elsewhere. The key is not using JSON as an intermediate step.
What's the difference between | and > for multi-line strings?
| is a literal block that keeps newlines as-is; > is a folded block that turns newlines into spaces. Use | for embedded scripts and > for long prose wrapped across lines. Adding - (|-) strips the final newline, and + keeps trailing blank lines.
Can parsing YAML be a security risk?
Yes. Some languages' default YAML loaders can instantiate arbitrary objects via tags, so parsing untrusted input can lead to code execution. Use yaml.safe_load in Python and YAML.safe_load in Ruby. JavaScript's js-yaml defaults to a safe schema, but check the options you pass to load.
How do I convert multiple --- separated documents?
A JSON document has exactly one top-level value, so several YAML documents can't map directly onto one JSON document. Convert each separately, or wrap them all in a JSON array. This comes up constantly with Kubernetes manifests.

💡 Note: If a YAML value arrives as the wrong type, it's almost always type inference. Check whether values that should be strings are quoted.

🔗Related Tools🔄 Text / Data