Toolium

JSON vs YAML: The Norway Problem and Other Reasons This Choice Matters

Hemanth Gedda7 min read

The JSON vs YAML debate is one of those technical questions where the right answer depends on who is writing the file and who is reading it. Both formats represent the same kinds of data - objects, arrays, strings, numbers, booleans, nulls - but they differ on aesthetics, tooling support, and a handful of subtle features that occasionally bite people. There is a famous YAML bug called the "Norway problem" that I want to talk about, plus the practical reasons Kubernetes picked YAML over JSON for its manifest format.

The basic difference

JSON uses braces, brackets, and quotes. Everything is explicit and unambiguous. The exact same object renders the same way every time.

{
  "name": "Alice",
  "roles": ["admin", "user"],
  "active": true
}

YAML uses indentation, dashes for lists, and tries to infer types from context. Quotes are optional when the value is unambiguous. Comments start with #.

# User configuration
name: Alice
roles:
  - admin
  - user
active: true

For configuration files that humans edit frequently, YAML wins on readability and the ability to leave comments. For data interchange between programs, JSON wins on being unambiguous and having universal parser support.

The Norway problem

YAML 1.1 - the version most YAML parsers still use as of 2026, despite YAML 1.2 having been published in 2009 - treats certain unquoted strings as booleans. The list includes obvious cases like "true" and "false," but also "yes," "no," "on," "off," and a few others.

The Norway problem: if you write a list of country codes in YAML, and one of them is the two-letter code for Norway (NO), the YAML parser converts it to the boolean false. So:

countries:
  - US
  - UK
  - NO

becomes countries: [US, UK, false] when parsed. Software that expects strings sees a boolean and breaks in confusing ways.

The fix is to quote the string explicitly. YAML 1.2 dropped the yes/no/on/off behavior, but YAML 1.1 is still the default in most parsers because of backward compatibility. The Toolium converter quotes strings that look like booleans, numbers, or dates when going JSON-to-YAML, to avoid this kind of round-trip bug.

Why Kubernetes uses YAML

Kubernetes' configuration is famously verbose, with manifests that can run hundreds of lines for a complex deployment. JSON for that would be brutal - every line indented inside braces, every key quoted, no comments allowed to explain why a particular setting exists.

YAML makes Kubernetes manifests at least somewhat readable. Comments explain non-obvious configuration. Multi-line strings (like inline shell scripts or config files) use block scalar syntax instead of escaping every newline. The hierarchical structure is visible at a glance from indentation.

Same reasoning for Docker Compose, GitHub Actions, GitLab CI, Ansible playbooks, and most modern infrastructure tools. The combination of "humans edit this" and "structure matters" lands on YAML.

Why APIs use JSON

For API request and response bodies, JSON wins because:

  • Universal parser support. Every language has a JSON parser in the standard library. YAML parsers are usually third-party dependencies.
  • Unambiguous. JSON's strict rules mean two parsers produce the same output. YAML's flexibility means parsers occasionally disagree on edge cases.
  • Faster to parse. JSON parsers are highly optimized. YAML parsers do more work because of the type inference.
  • Smaller wire format. JSON omits the indentation that YAML uses for structure, so JSON is more compact for the same data.

If your data has to travel over the network at high volume, JSON is the right choice. If your data lives in a file that a human will edit, YAML.

The comments issue

JSON has no comments. There is no // or /* */ syntax; the spec is explicit that comments are not allowed. The standard workaround in JSON config files is to add a "_comment" or "$comment" field with the comment text, but this is ugly and confuses some validators.

This is the single biggest reason YAML wins for human-edited files. Real-world config files need annotations. "This setting is high because of bug XYZ." "Do not lower this without testing." "The reason this is duplicated is because..." Without comments, all of this context lives in commit messages or external documentation, where it gets lost.

Round-tripping

If you convert JSON to YAML and back to JSON, do you get the same JSON? Mostly yes, with caveats:

  • Whitespace and key order may differ.
  • YAML preserves the original key order; JSON parsers usually do too, but the language spec does not require it.
  • Some edge cases with very precise numbers (more than 15 significant digits) may lose precision.
  • YAML anchors and aliases get expanded during conversion to JSON and cannot be restored.

For typical data, the round-trip preserves values exactly. The Toolium JSON/YAML Converter handles both directions and warns when something might not round-trip cleanly.

Practical recommendations

  • API responses: JSON.
  • Configuration files for any modern tool: YAML.
  • Configuration files for older tools: JSON (some legacy tools only read JSON).
  • Anywhere a strict, unambiguous format is needed: JSON.
  • Anywhere comments and human-readability matter: YAML.
  • Data that needs to be edited by both humans and programs: YAML, with a JSON schema for validation.

For the rare case where you want comments AND strict parsing, JSON5 or HJSON exist as JSON-with-comments formats. They are not widely supported and I would only recommend them for projects where you control all the tooling.

Try the tool mentioned in this article

Open tool