I’ll be honest — I’ve spent more time debugging config files than I’d like to admit. Not because the logic was wrong, but because I picked the wrong format for the job, or made a silly YAML indentation mistake that silently broke everything.
If you’ve ever stared at a CI pipeline failure for 20 minutes only to realize it was a tab character in your YAML, this one’s for you.
JSON and YAML: A Quick Reality Check
Both formats store structured data. Both are widely supported. But they solve slightly different problems, and choosing the wrong one in the wrong context leads to frustrating bugs.
Here’s the practical difference:
| Aspect | JSON | YAML |
|---|---|---|
| Readability | Verbose, but explicit | Clean, minimal syntax |
| Comments | Not supported | Supported with # |
| Data types | Strings, numbers, booleans, null, arrays, objects | All JSON types + dates, multiline strings, anchors |
| Indentation sensitivity | None (uses braces/brackets) | Whitespace-sensitive |
| Trailing commas | Not allowed | Not applicable |
| Error surface | Small — strict syntax catches issues early | Large — silent failures from bad indentation |
| Best for | APIs, package.json, machine-to-machine | Docker Compose, K8s manifests, CI/CD configs |
Mistake #1: Using Tabs in YAML
This is the classic. YAML strictly requires spaces for indentation — tabs are illegal. But most editors don’t visually distinguish tabs from spaces, so you won’t see the problem until your pipeline explodes.
# This looks fine but will fail if indented with tabs
services:
web:
image: nginx
ports:
- "80:80"
The error you’ll see:
yaml: line 2: found character '\t' that cannot start any token
The fix: Configure your editor to insert spaces when you hit Tab in .yaml files. In VS Code, add this to your settings:
"[yaml]": {
"editor.insertSpaces": true,
"editor.tabSize": 2
}
I cannot stress this enough — this single setting will save you hours over the course of a year.
Mistake #2: YAML’s Implicit Type Coercion
This one is genuinely dangerous. YAML tries to be “smart” about types, which means it silently converts values you intended as strings into something else entirely.
# What you wrote
country_code: NO
version: 1.0
api_key: 0123456
deploy: on
# What YAML actually parsed
country_code: false # "NO" → boolean false
version: 1 # 1.0 → integer 1 (in some parsers)
api_key: 42798 # Leading zero → octal number
deploy: true # "on" → boolean true
I once spent an afternoon debugging why a Norwegian user’s locale wasn’t loading. The country code NO was being parsed as false. Fun times.
The fix: Always quote strings that could be misinterpreted:
country_code: "NO"
version: "1.0"
api_key: "0123456"
deploy: "on"
JSON doesn’t have this problem because every string must be explicitly quoted. There’s no ambiguity.
Mistake #3: Trailing Commas in JSON
This one catches JavaScript developers constantly. In JS, trailing commas are fine. In JSON, they’re a syntax error.
{
"name": "my-project",
"version": "2.1.0",
"private": true,
}
The error you’ll see:
SyntaxError: Unexpected token } in JSON at position 65
That error message tells you almost nothing useful. You’re left scanning the file for the problem.
The fix: Use a JSON formatter that highlights these issues instantly. Or better yet, paste your JSON into a JSON Formatter — it’ll point directly to the problematic line.
Some modern tools (like jsonc parsers in VS Code) support trailing commas, but if your config is consumed by a strict JSON parser, you’ll still hit this wall.
Mistake #4: Multiline Strings Gone Wrong
Need to embed a long command or SQL query in a config file? This is where YAML shines and JSON struggles.
JSON — the ugly way:
{
"script": "echo 'Starting deploy' && npm run build && npm run test && echo 'Deploy complete'"
}
You can’t break this across lines in JSON. Every string must be on a single line (unless you use \n escape characters, which are hard to read).
YAML — the clean way:
script: |
echo 'Starting deploy'
npm run build
npm run test
echo 'Deploy complete'
The | preserves line breaks. Use > if you want the lines folded into a single line. The distinction matters:
|→ keeps newlines (literal block)>→ folds newlines into spaces (folded block)
Common mistake: Forgetting which symbol does what, or mixing up | with |- (which strips the trailing newline). If your script is running but behaving oddly, check whether extra newlines are sneaking in.
Mistake #5: JSON Comments (or Lack Thereof)
At some point, every developer tries this:
{
// API endpoint for production
"api_url": "https://api.example.com",
"timeout": 30
}
JSON doesn’t support comments. Period. The spec intentionally excludes them (Douglas Crockford’s reasoning was that comments were being used to embed parsing directives, which defeated the purpose of a simple data format).
Workarounds:
- Switch to YAML if you need comments in config files
- Use JSONC (JSON with Comments) — supported by VS Code’s
settings.jsonand TypeScript’stsconfig.json - Use a
_commentfield as a hack (not great, but it works):
{
"_comment": "API endpoint for production",
"api_url": "https://api.example.com"
}
So Which One Should You Use?
After years of working with both, here’s my rule of thumb:
Use JSON when:
- The file is read/written by machines (APIs,
package.json, data exchange) - You want strict validation — JSON’s rigidity catches errors early
- You’re working in a JavaScript/TypeScript ecosystem where JSON is native
- The config is simple and flat
Use YAML when:
- Humans will read and edit the file frequently (Docker Compose, CI configs)
- You need comments to explain why certain values are set
- The config is deeply nested and would be unreadable in JSON
- You need multiline strings or complex data structures
Use neither when:
- You need environment-specific overrides → consider
.envfiles or TOML - You need executable logic in your config → use a
.jsor.tsconfig file
Converting Between Formats
When you need to migrate a config from one format to the other, doing it manually is tedious and error-prone. I built a YAML to JSON converter specifically for this — paste your YAML, get clean JSON, or vice versa. It handles edge cases like multiline strings and nested anchors that would be painful to convert by hand.
Final Thoughts
The “JSON vs YAML” debate isn’t really about which format is better. It’s about which format causes fewer bugs in your specific context. JSON is stricter and catches more errors at parse time. YAML is more expressive but has a wider error surface.
Pick the one that fits your use case, configure your editor properly, and save yourself the debugging headaches.
Part of our JSON Developer Guide series. You might also find JSON vs XML: A Practical Comparison useful.