X Xerobit

YAML vs JSON: Which to Use When (and Why It Matters)

JSON is for machines, YAML is for humans, and choosing the wrong one quietly costs you weeks of debugging. The honest comparison and the rules for picking.

Mian Ali Khalid · · 10 min read
Use the tool
YAML ↔ JSON Converter
Convert between YAML and JSON formats with full fidelity.
Open YAML ↔ JSON Converter →

You’re picking a config format for a new service. You ask in chat: JSON or YAML? Half the team votes JSON because it’s strict and parsers are everywhere. The other half votes YAML because the configs they write by hand are nicer to read. Both sides are right. Both sides are wrong. The choice depends on who reads the file, who writes it, and what kind of pain you’d rather have.

This post is the honest comparison. Where each format wins, where each one bites, and the decision rules that actually hold up in practice.

What’s the difference between YAML and JSON?

YAML and JSON both represent the same set of data structures — strings, numbers, booleans, null, arrays, and maps — but JSON uses explicit syntax (braces, brackets, quotes) suited for machines, while YAML uses indentation and looser typing for human readability. JSON is a strict subset of YAML 1.2: every JSON document is valid YAML, but most YAML is not valid JSON.

The same payload in both:

{
  "service": "api",
  "replicas": 3,
  "env": ["staging", "production"],
  "owner": {
    "team": "platform",
    "oncall": "ada@example.com"
  }
}
service: api
replicas: 3
env:
  - staging
  - production
owner:
  team: platform
  oncall: ada@example.com

Same data. The YAML is a third shorter and easier to scan. The JSON is unambiguous and machine-strict.

Where YAML wins

Hand-edited configuration files. Kubernetes manifests, GitHub Actions workflows, Ansible playbooks, Docker Compose files, CI configs. These are read and modified by humans more often than they’re written by machines. The reduced syntactic noise (no braces, no required quotes, comments allowed) makes a real difference at the 100-line and 500-line scale.

Comments matter. YAML supports # inline comments. JSON does not. For configs with explanatory context — why this timeout is 30s, why this flag is set — comments are not optional. Workarounds like JSONC (JSON with comments) exist but aren’t universally supported.

Multi-document files. YAML can hold multiple documents in one file separated by ---. Useful for Kubernetes manifests where one file declares a Deployment, a Service, and a ConfigMap.

Anchors and references. YAML’s &anchor and *alias let you reuse blocks within a single document. Helpful for config files where the same logging or metrics block applies to ten services. JSON has no equivalent — you copy-paste.

Multiline strings without escaping. Block scalars (| and >) let you write multi-line strings with their natural newlines:

script: |
  echo "starting"
  npm install
  npm test

In JSON you’d need "echo \"starting\"\nnpm install\nnpm test". Painful at scale.

Where JSON wins

Wire format. APIs, streams, log lines, database columns. JSON parsers are an order of magnitude faster than YAML parsers, exist in every language without dependencies, and have stable, narrowly-defined semantics. When two systems exchange data, JSON is almost always the right answer.

Strictness as a feature. JSON has one way to write a string (double-quoted), one way to write true, one way to express a number. YAML has at least seven ways to write true: true, True, TRUE, yes, Yes, on, y. That flexibility helps humans and confuses machines. The Norway problem is the famous case: writing country: NO and getting country: false because NO parses as the boolean false in YAML 1.1.

No indentation traps. YAML’s whitespace-sensitive syntax means tabs vs spaces can break parsing, and a misaligned key silently changes the document structure. JSON’s brace-and-bracket syntax is unambiguous: errors fail loudly at the first wrong character. We covered the failure modes in the JSON validation errors post.

Tooling depth. JSON has JSONPath, JSON Schema, JSON Patch (RFC 6902), JSON Pointer (RFC 6901), JMESPath, jq, and a hundred linters. YAML has yamllint and one schema validator. If you need to programmatically query or transform documents, JSON is decades ahead.

Determinism in serialization. Round-trip parsing of YAML loses information — comments, key ordering, anchor structure. JSON round-trips lossy in only one place (key order, which is officially unordered). For storage and audit, JSON’s loss is bounded; YAML’s isn’t.

The Norway problem in detail

YAML 1.1, which most parsers still default to, treats a long list of unquoted strings as booleans:

countries:
  - US
  - GB
  - NO
  - FR

The NO in that list is parsed as the boolean false in YAML 1.1. So is n, No, false, False, off, Off, OFF. A list of country codes silently becomes ["US", "GB", false, "FR"]. The Norwegian airline group hit this exactly — country: NO became country: false. The code shipped a bug because the input file looked correct.

The fix is to quote ambiguous values: - "NO". Or use YAML 1.2, which restricts boolean parsing to lowercase true/false only. Or use JSON, which has no such ambiguity because everything is explicitly typed at the syntactic level.

Type coercion ambiguities in YAML 1.1:

  • 1.0, 1.5, 1e3 are floats
  • 0x1F, 0o17, 017 are integers (octal!)
  • null, Null, NULL, ~, empty value are all null
  • 2026-05-02 is a Date object, not a string
  • 12:34:56 is a Time object in some parsers

Most of this is “fixed” in YAML 1.2, but most parsers don’t default to 1.2. Always check what version your parser uses.

Performance: JSON is dramatically faster

Benchmarks vary, but parsing JSON is typically 10–50× faster than parsing YAML, with a smaller memory footprint. The reason is structural: JSON’s grammar is tight and unambiguous, so a parser can be a tight state machine. YAML’s grammar is significantly more complex (anchors, aliases, type tags, multi-document, indentation modes) and inherently slower.

If you’re parsing 1000 documents on a request path, this matters. If you’re loading one config at startup, it doesn’t. Pick the format that fits the use case, not the benchmark.

When to use which: the rules

Use JSON when:

  • The file is read or written by software more than humans
  • The data is exchanged over the wire (APIs, streams, log lines)
  • You need fast parse times at runtime
  • You need formal schema validation (JSON Schema)
  • You need precise round-trip preservation

Use YAML when:

  • The file is hand-edited regularly (CI configs, K8s manifests, Compose files, Ansible)
  • Comments are valuable
  • You need anchors/aliases to avoid duplication in a single file
  • Readability of multi-line content matters more than parse speed

Use TOML when:

  • It’s a config file shorter than 500 lines
  • You want hand-editability without YAML’s type ambiguity
  • Examples: pyproject.toml, Cargo.toml

Use JSON5 or JSONC when:

  • You want JSON syntax but need comments or trailing commas
  • Examples: tsconfig.json, VS Code settings

Converting between them

For one-off conversions, paste the document into the YAML to JSON converter — it round-trips both directions and validates against the YAML 1.2 spec.

Programmatically:

  • Python: pyyaml (set Loader=SafeLoader), json builtin
  • JavaScript/TypeScript: js-yaml for YAML, native JSON
  • Go: gopkg.in/yaml.v3, encoding/json
  • Rust: serde_yaml, serde_json

Critical detail: in Python, never use yaml.load(input) without specifying a Loader. The default in older versions of PyYAML executes arbitrary Python code on YAML tags — a remote code execution vulnerability. Always use yaml.safe_load(input) or pass Loader=yaml.SafeLoader.

A working principle

JSON is for machines, YAML is for humans. The cost of using JSON for a hand-edited config is minor irritation. The cost of using YAML for a wire format is performance, occasional silent type coercion bugs, and a more complex parsing layer.

When you’re not sure: pick the format whose downside you can tolerate. Bad JSON config means a slightly noisier file. Bad YAML wire data means a quiet bug in production six weeks from now.

If you’re shipping internal tooling and the team will edit it daily, lean YAML. If you’re building a public API or a log pipeline, lean JSON. If you’re writing a Kubernetes manifest, you don’t have a choice — it’s YAML.

Further reading


Related posts

Related tool

YAML ↔ JSON Converter

Convert between YAML and JSON formats with full fidelity.

Written by Mian Ali Khalid. Part of the Data & Format pillar.