You've probably noticed that some projects use .json files for config while others use .yaml or .yml. Both formats represent structured data. Both are human-readable. So what's the actual difference, and when should you reach for one over the other?

I've used both extensively — JSON is my daily driver for APIs and data exchange, YAML is my go-to for Kubernetes manifests, GitHub Actions, and Docker Compose. They solve similar problems but they have very different personalities.

Side by Side: The Same Config in Both Formats

Here's a database config object written in JSON:

json
{
  "database": {
    "host": "localhost",
    "port": 5432,
    "name": "myapp",
    "ssl": true,
    "pool": {
      "min": 2,
      "max": 10
    },
    "replicas": ["replica1.db", "replica2.db"]
  }
}

And here's the same config in YAML:

yaml
database:
  host: localhost
  port: 5432
  name: myapp
  ssl: true
  pool:
    min: 2
    max: 10
  replicas:
    - replica1.db
    - replica2.db

YAML is visibly less cluttered. No quotes around most strings, no curly braces, no commas. For a config file that humans edit regularly, that clarity adds up. But YAML achieves this by being significantly more complex under the hood.

Where YAML Shines

  • Human-editable config files. CI/CD pipelines (GitHub Actions, GitLab CI), Kubernetes manifests, Docker Compose, Ansible playbooks. All YAML. No coincidence — these are files humans write by hand.
  • Comments. YAML supports comments with #. This is huge for config files where you want to explain why a setting is what it is. JSON doesn't support comments at all.
  • Multi-line strings. YAML has block scalars for multi-line content that read naturally. JSON requires \n escape sequences.
  • Less visual noise. No requirement to quote most strings, no closing braces, no trailing commas to worry about.
  • Anchors and aliases. YAML lets you define a value once and reference it elsewhere with &anchor and *alias — handy for DRY config files.

Where JSON Wins

  • Strictness. JSON has one valid representation for any given data structure. YAML has a dozen ways to write the same thing, which creates inconsistency across teams.
  • No indentation traps. JSON uses braces and brackets. YAML uses indentation, which means a single misplaced space can silently break your entire config.
  • Parse performance. JSON parsers are fast and simple. YAML parsers are complex — YAML 1.1 has notoriously tricky implicit type coercion rules.
  • Universal library support. Every language has a battle-tested, zero-dependency JSON parser. YAML libraries vary in quality and spec compliance.
  • Tooling. Linters, formatters, schema validators — JSON tooling is more mature and widely available.
  • API payloads. JSON is the universal language of web APIs. Sending YAML over HTTP would be unconventional and cause friction.

The YAML Gotchas That Will Burn You

YAML has some genuinely surprising behaviours that have caused real production incidents. Most of them come from the implicit type rules in YAML 1.1, which YAML 1.2 tightened up. Know these before you rely on YAML for anything critical:

The Norway Problem: In YAML 1.1 (used by many older tools), the string NO is parsed as boolean false. Country codes like NO (Norway), NO, and others get silently converted to booleans. YAML 1.2 fixed this, but not all parsers have caught up.
yaml
# YAML 1.1 implicit type coercion — all of these become booleans:
enabled: yes   # → true
disabled: no   # → false
country: NO    # → false (!)  ← the Norway Problem

# Safe practice: quote strings that look like booleans
country: "NO"
enabled: "yes"
  • Octal integers. In YAML 1.1, 010 parses as 8 (octal), not 10. Relevant for things like file permissions.
  • Tabs vs spaces. YAML forbids tabs for indentation. Mix in one tab from a code editor and your file breaks silently or throws a cryptic error.
  • Implicit nulls. An empty value in YAML becomes null. Easy to miss when editing by hand.
  • String vs number ambiguity. port: 8080 gives you an integer. version: 1.0 might give you a float. Sometimes you want the string "1.0". Always quote when it matters.

Practical Decision Guide

Reach for YAML when:

  • Writing config files that humans edit directly: CI/CD, Kubernetes, Docker Compose, Ansible
  • The file will have comments explaining the settings
  • Multi-line string values are common
  • The ecosystem you're working in already uses YAML (don't fight the convention)

Reach for JSON when:

  • Sending or receiving data over an API
  • The data is generated and consumed programmatically (no human editing)
  • You need guaranteed parse consistency across different tools and languages
  • Working in an ecosystem that standardises on JSON: npm (package.json), VS Code (settings.json), Angular, TypeScript

Converting Between the Two

Need to convert YAML config into JSON for a tool that doesn't speak YAML? Use the YAML to JSON converter. Going the other way? The JSON to YAML converter will handle it. The YAML Formatter is also handy when you paste YAML that's gotten misaligned. And if your YAML won't parse, the YAML Validator will tell you exactly where the problem is.

The Bottom Line

JSON and YAML are complementary, not competing. Use JSON for data exchange — APIs, programmatic data storage, serialisation. Use YAML for config files that humans read and edit. Most mature projects use both: package.json for dependencies, .github/workflows/*.yml for CI. Once you understand what each format is optimised for, the choice becomes obvious.