DevTools Hub

Search tools

Search for a developer tool

JSON vs YAML

Part of the JSON Toolkit

Both represent the same underlying data — objects, arrays, strings, numbers, booleans, null — and every valid JSON document is, in fact, valid YAML. So why does one dominate API responses and the other dominate config files? The differences that matter aren't about what data they can represent, but about who's meant to read and write them.

The short answer

JSON is optimized to be generated and parsed by machines: a small, strict, unambiguous grammar with no room for a parser to guess what you meant. YAML is optimized to be written and read by humans: comments, unquoted strings, no required braces or commas, and reuse via anchors — all of which make it pleasant to hand-author, and all of which make it a meaningfully harder format to parse correctly. Neither is a strict upgrade of the other; they were designed for different primary readers. For YAML's syntax on its own, see What Is YAML?

Side by side

The same data, in both formats:

// JSON
{
  "name": "api-server",
  "port": 8080,
  "tags": ["production", "backend"]
}
# YAML
name: api-server
port: 8080
tags:
  - production
  - backend

No quotes around keys or plain strings, no commas between items, no closing brace to match up — YAML strips out most of the punctuation JSON requires. That's a real readability win for a file a person edits by hand, and a real cost for a parser: JSON's grammar can be described in about a page, while significant whitespace, multiple string styles, and implicit typing make YAML's considerably larger.

Comments and reuse — YAML has both, JSON has neither

JSON has no comment syntax at all, by design — JSON.parse rejects a // or # line outright. YAML supports # comments natively, which matters constantly in config files that need a "why" next to a setting.

YAML also has anchors and aliases for referencing the same value more than once in one document — something JSON has no mechanism for at all:

defaults: &defaults
  timeout: 30
  retries: 3
service_a:
  <<: *defaults
  port: 8080
service_b:
  <<: *defaults
  port: 9090

&defaults names that block, *defaults and the << merge key pull its keys into service_a and service_b — both end up with timeout and retries without repeating them. In JSON, the same defaults would have to be copy-pasted into every object, or resolved by whatever code reads the file rather than the format itself.

Typing: explicit vs. inferred

Every JSON value's type is unambiguous from its literal syntax — "30" is always a string, 30 is always a number, there's no third reading. YAML infers types from unquoted scalars, which is convenient right up until it isn't: under older YAML 1.1 rules, an unquoted no, yes, or the country code NO gets silently read as a boolean instead of a string — the classic "Norway problem," covered in more detail in What Is YAML?. JSON has no equivalent failure mode, because it has no equivalent convenience: if you wanted a string, you wrote the quotes.

A security difference worth knowing

Several YAML libraries historically shipped a "load" function that could deserialize arbitrary language-native objects using special tags in the document — not just plain data. Pointed at untrusted input, that's a real code-execution risk, which is why most YAML libraries now ship a safe-by-default loader (or a clearly separate unsafe one) that restricts parsing to plain data types. JSON has no equivalent danger: its parser only ever produces strings, numbers, booleans, null, objects, and arrays — there's no tag syntax to abuse in the first place. If you're parsing YAML from a source you don't fully trust, confirm your library defaults to (or is explicitly configured for) safe loading.

When to use which

  • Machine-to-machine data (API requests and responses, event payloads, anything generated and consumed by code) → JSON. It's faster to parse, has no ambiguity to resolve, and every language has a JSON parser in its standard library.
  • Human-authored configuration (Kubernetes manifests, CI pipelines, Docker Compose, application config) → YAML. Comments and anchors are worth the parsing complexity when a person is the one writing and maintaining the file.
  • Both, in practice — plenty of tools read YAML config and emit JSON over the wire, or the reverse. Picking the right one is about who's touching the file directly, not a rule that applies to a whole system uniformly.

Common misconceptions

  • "YAML is just JSON with different punctuation." Close, but not quite — the anchor/alias/merge-key system and comments have no JSON equivalent, and type inference means the same-looking value can parse differently depending on the schema version in use.
  • "JSON is a subset of YAML, so any YAML tool understands JSON." True in the other direction — valid JSON parses as valid YAML — but a JSON-only parser will reject perfectly valid YAML the moment it hits a comment, an anchor, or an unquoted multi-word string.
  • "Converting between them is lossless." Usually, but not always — comments and anchors don't survive a round trip through a JSON intermediate representation, since JSON has nowhere to put them.

Try it yourself

Validate a YAML file's syntax with YAML Validator, or format and validate JSON with JSON Formatter and JSON Validator. All three run entirely in your browser.

Related tools