Data formats · August 28, 2026

YAML vs JSON — when to use which, and why most teams use both

YAML and JSON look interchangeable on the surface, but they optimise for different audiences. Here's how to pick the right format for config files, APIs, CI pipelines, and Kubernetes manifests.

If you’ve ever opened a Kubernetes manifest, a GitHub Actions workflow, or a docker-compose file, you’ve used YAML. If you’ve ever called a REST API or written a config file for a Node.js project, you’ve used JSON. They’re both serialization formats. They both describe the same kinds of data structures — maps, arrays, strings, numbers, booleans, null. So why do we have two of them?

The short answer: YAML optimises for humans, JSON optimises for machines. The long answer involves a few decades of developer experience, a few committee meetings, and a surprising amount of edge cases. Let’s walk through it.

What JSON is good at

JSON (JavaScript Object Notation) was popularised in the early 2000s as a payload format for AJAX requests. It was deliberately small — six value types, no comments, no trailing commas, no ambiguity. That strictness is its superpower on the wire:

  • Parsers are tiny and fast. JSON.parse ships with every browser and every language runtime. There’s nothing to think about.
  • Errors are unambiguous. When JSON is broken, the parser tells you exactly which line and column.
  • Machines agree on semantics. A number is a number, a string is a string, true is true. There is no “is yes a boolean or a string?” debate.

That’s why JSON is the lingua franca of APIs. When two services are talking, you want the format with the fewest surprises.

What YAML is good at

YAML (YAML Ain’t Markup Language) was designed for configuration files written by humans. It traded some of JSON’s strictness for readability:

  • No braces, no brackets. Structure is indentation. A docker-compose.yml reads top-to-bottom like a list.
  • Comments. A # starts a comment. JSON has no comment syntax — and the lack of comments is the single most common reason teams move from JSON to YAML for config files.
  • Anchors and references. &anchor and *reference let you define a value once and reuse it. JSON has no equivalent; you have to copy-paste. Learn more in our YAML anchors explained guide.
  • Multi-line strings. Literal blocks (|) and folded blocks (>) handle prose and code without escape-juggling.

That’s why YAML dominates in places humans read and write by hand: Kubernetes, GitHub Actions, GitLab CI, Ansible playbooks, docker-compose, CloudFormation, OpenAPI specs, and the 2025-era surge of AI-agent config files (.github/agents.yml, MCP server manifests, evaluation harnesses).

The asymmetry

Here’s the dirty secret: YAML is a superset of JSON’s data model. Every valid JSON file can be expressed as YAML, but the reverse isn’t true. YAML has features JSON simply doesn’t have — comments, anchors, multi-doc files, custom tags. Once you write YAML with anchors, you can’t losslessly convert it back to JSON. The anchors disappear.

This matters for tooling. If you have a YAML file with &defaults *defaults, converting to JSON will either expand the references (silently producing a larger file) or drop them (silently producing a smaller file). The same goes for comments. JSON has nowhere to put them.

When to use which

Use JSON when:

  • You’re sending data over the network (APIs, message queues, event payloads).
  • The file is read by code, not humans.
  • You want unambiguous error messages from strict parsers.
  • You’re optimising for parse speed on constrained devices.

Use YAML when:

  • A human is the primary author and reader of the file.
  • You want comments for explaining intent.
  • You want to reuse chunks of config with anchors.
  • The tooling in your domain expects it (Kubernetes, CI, etc.).

The pragmatic answer for most teams: JSON for the wire, YAML for config, both for data interchange. When in doubt, store the canonical version in JSON (lossless) and emit YAML for human consumption (with comments and anchors) only when the audience is a developer opening a text editor.

Common pitfalls when converting between the two

  1. Numbers and booleans are auto-typed in YAML. port: 8080 is a number. port: "8080" is a string. Forgetting to quote can change your type.
  2. Anchors and comments are dropped in JSON. No way around this — the format has no place to put them.
  3. YAML null is ambiguous. key: (empty value) is null. key: null is also null. key: "" is an empty string. Three different things.
  4. Tabs break YAML. Indentation must be spaces. Tabs are an error.
  5. YAML 1.1 vs 1.2 vs 1.2.2. YAML 1.1 treated yes, no, on, off as booleans. YAML 1.2 (the spec used by js-yaml, PyYAML, and most parsers in 2026) does not. The 1.2.2 maintenance release in 2025 tightened a few edge cases around document-end markers and BOM handling — most parsers adopted the fixes silently. If you’re moving from a 2018-era codebase, your config might still break in subtle ways.

Tools that help

When you’re moving between the two — and you will, because every team uses both — a fast client-side converter is your friend. The YAML to JSON and JSON to YAML tools on DevSpeedTools run entirely in your browser, so config files with secrets never leave your machine. Open DevTools → Network and you’ll see no requests carrying your data.

For YAML that’s grown messy over time, the YAML formatter will normalise indentation to two spaces and fix inconsistent quoting. For files that won’t parse, the YAML validator shows you the exact line and column of every error.

The bottom line: stop treating YAML and JSON as competing formats. They’re complementary. The right format depends on who’s reading the file — a machine, or a tired developer at 11pm trying to figure out why their deployment is broken.