YAML vs JSON for Configuration: The Real Tradeoffs
YAML won the Kubernetes era. JSON owns the API era. But for application config files in 2026, the choice between them is non-obvious — each format has idiosyncratic failure modes that bite teams in production. Here is the practitioner's comparison.
The high-level scorecard
| Criterion | YAML | JSON |
|---|---|---|
| Human-readable | Better | Worse |
| Comments | Yes | No |
| Type ambiguity | Bad | Strict |
| Multi-line strings | Excellent | Awful |
| Schema validation | Mature | Mature |
| Parser performance | Slower | Faster |
| Security risks | Significant | Minimal |
| Whitespace-sensitive | Painfully | No |
The Norway problem (and other YAML traps)
YAML's spec auto-types unquoted values. The result:
countries:
- US
- GB
- NO # This is parsed as boolean false!
- SE
Norway's country code NO is a "false" synonym in YAML 1.1. So is off, n, no. And yes, y, on become true. Quote your strings always.
Other YAML gotchas
- Number-like strings:
version: 1.10is parsed as the float 1.1, not the string "1.10". - Sexagesimal:
port: 22:00:00is parsed as the number 79200 (22*3600+0). - Octal:
mode: 0640may or may not be parsed as octal depending on parser version. - Mixed indentation: tabs and spaces don't mix; some parsers fail silently.
- Anchors and aliases:
&anchor/*anchorcan cause infinite loops in adversarial input.
JSON's main issues
- No comments. Forces external documentation or filename hacks like
"_comment": "...". - No multi-line strings. Long strings become unreadable single lines.
- No trailing commas. Adding a new field at the end requires editing two lines.
- Quote-heavy. Every key is quoted, which adds visual noise for human-edited files.
The "use YAML" arguments
- Kubernetes, GitHub Actions, GitLab CI, Ansible, CircleCI — the entire DevOps tooling ecosystem standardized on YAML
- Multi-line strings (Helm chart values, embedded shell scripts) need YAML's literal block scalar (
|) - Comments are essential for config files explaining "why"
The "use JSON" arguments
- Strict typing — numbers are numbers, strings are strings, no surprises
- Faster parsers (10-100x in some cases)
- Same format as your API responses — fewer mental contexts
- Trivial security profile — no remote code execution risk
- Universally supported in every language stdlib
The hybrid: JSON5
JSON5 is JSON with comments, trailing commas, unquoted keys, and single quotes. Most of YAML's ergonomics without the type ambiguity:
{
// API endpoint
baseUrl: 'https://api.example.com',
timeout: 5000,
retry: {
attempts: 3,
backoff: 'exponential', // trailing comma OK
}
}
Parsers exist for every major language. If you're choosing config format for a new project today, JSON5 is often the right answer.
The hybrid: TOML
TOML (used by Cargo, Hugo, Poetry) is another option. INI-like sections, JSON-like values, less weird than YAML. Worth considering if you don't need deep nesting.
Decision matrix
| Use case | Best format |
|---|---|
| Kubernetes / Helm | YAML (forced) |
| API request/response | JSON |
| App config (small) | JSON5 or TOML |
| App config (large, nested) | YAML or HCL |
| CI/CD pipelines | YAML (forced) |
| Static site config | TOML or YAML |
| Programmatic generation | JSON |
| Human-edited often | YAML or JSON5 |
Converting between
Use JSON to YAML and YAML to JSON for ad-hoc conversions. For pipelines, use yq (the YAML cousin of jq) — it handles both formats and converts natively.
Schema validation
Both YAML and JSON can be validated against JSON Schema:
- JSON: ajv (Node), jsonschema (Python), gojsonschema (Go)
- YAML: same libraries, but parse to objects first — schema applies to the data, not the syntax
For Kubernetes specifically, the API server validates against OpenAPI schemas embedded in the cluster.
Security: the YAML deserialization risk
PyYAML's load() function (NOT safe_load()) executes Python objects in YAML. Adversarial YAML input can run arbitrary code. Always:
importyaml yaml.safe_load(content)# Use thisyaml.load(content)# NEVER on untrusted input
Bottom line
Use YAML when the ecosystem demands it (Kubernetes, CI/CD). Use JSON when machines are the primary consumer. Use JSON5 or TOML when humans edit the file often and you control the parser. Always quote strings in YAML, always use safe_load, and convert formats as needed.
Try the free dev tools suite
15+ tools. 100% client-side. No signup. No tracking.
Browse all tools →