JSON and YAML solve the same problem — representing structured data as text — with very different philosophies. JSON optimizes for machines; YAML optimizes for humans. After working with both formats across hundreds of projects, here's our honest take on when each one wins.

The same data, two ways

Let's start with the same data expressed in both formats. Here's a typical Kubernetes-style configuration:

{
  "apiVersion": "v1",
  "kind": "Service",
  "metadata": {
    "name": "my-app",
    "labels": {
      "app": "frontend",
      "tier": "production"
    }
  },
  "spec": {
    "selector": { "app": "my-app" },
    "ports": [
      { "port": 80, "targetPort": 8080 }
    ]
  }
}

And the same in YAML:

apiVersion: v1
kind: Service
metadata:
  name: my-app
  labels:
    app: frontend
    tier: production
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

Both express the same underlying data. The YAML version is about 30% shorter and (most people would say) easier to read. The JSON version is more explicit about structure — every boundary is marked with punctuation.

Syntax differences that matter

JSON uses punctuation for structure. Braces denote objects, brackets denote arrays, quotes denote strings, commas separate items. Every boundary is unambiguous. The downside: more keystrokes when writing by hand, more visual noise when reading.

YAML uses indentation for structure. The level of indentation determines nesting depth. This is more compact but also more error-prone — accidentally adding or removing a space can change the meaning of your document. The infamous "Norway problem" is YAML's: NO (the country code for Norway) gets parsed as the boolean false in YAML 1.1 because no is one of its boolean keywords.

YAML allows comments. JSON doesn't. This is often the single deciding factor. Configuration files benefit enormously from inline explanation. package.json in Node.js is famously frustrating to maintain partly because you can't comment why a specific dependency version was pinned.

YAML has anchors and references. You can define a value once and reference it elsewhere:

defaults: &defaults
  timeout: 30
  retries: 3

production:
  <<: *defaults
  host: prod.example.com

staging:
  <<: *defaults
  host: staging.example.com

JSON has no equivalent — you'd have to repeat the values or use a templating layer on top.

When JSON wins

When YAML wins

The hybrid pattern

A common arrangement in modern systems: humans edit YAML configs, but the build pipeline converts them to JSON before runtime. This gives you the readability of YAML during authoring and the parsing speed of JSON during execution. Our JSON ↔ YAML converter handles this conversion in either direction.

This pattern works particularly well for:

YAML gotchas to know about

The Norway problem. In YAML 1.1 (still the default for many libraries), the unquoted string NO becomes the boolean false. Same for YES, ON, OFF. To preserve a literal string that looks like a boolean, quote it: country: "NO".

Tabs are illegal for indentation. YAML insists on spaces. Most editors handle this automatically, but if you switch between editors, mismatched tabs and spaces can break parsing in subtle ways.

Indentation must be consistent. Within a single block, all items at the same level must be indented identically. Most YAML errors come from accidentally mismatching indentation.

Implicit typing surprises. Versions like 1.10 parse as the float 1.1 in YAML 1.1 (trailing zeros lost). To preserve, use version: "1.10". Sexagesimal numbers (1:23:45) might parse as base-60 numerics. Always quote ambiguous values.

JSON gotchas to know about

No trailing commas. Valid in JavaScript, invalid in JSON. {"a": 1,} fails to parse. This is the #1 cause of "invalid JSON" errors.

Double quotes only. Single quotes around strings or keys cause parse failures.

No comments. Period. If you need comments, use JSONC (for VS Code) or JSON5, or switch to YAML.

Number precision. JSON numbers are IEEE 754 doubles — integers above 2^53 lose precision. For 64-bit IDs, encode as strings.

The verdict

Use JSON for: APIs, programmatic data interchange, large data files, anywhere humans aren't editing the file directly. Use YAML for: configuration files that humans edit, CI/CD pipelines, Kubernetes manifests, anywhere the readability matters more than parsing speed.

When in doubt, ask: who edits this file? If the answer is "a program," choose JSON. If the answer is "a person," choose YAML.

And remember — you can have both. Authoring in YAML, runtime in JSON, with a build step doing the conversion, is a perfectly normal pattern.