Use YAML for config files that people edit by hand, because it allows comments and is easier to read. Use JSON when a program writes the file, when another program needs to read it with no surprises, or when the tool simply requires JSON. If you pick YAML, quote anything that could be mistaken for a boolean or a number.
The short verdict
| What changes the decision | JSON | YAML |
|---|---|---|
| Comments | None. The spec has no comment syntax | # comments anywhere |
| Who writes it | Programs, or people who don't mind braces and quotes | People |
| Type surprises | Few: strings are always quoted | Unquoted no, on or y can become booleans on older parsers |
| Whitespace | Insignificant | Indentation is structure; tabs aren't allowed for it |
| Parser support | Built into most languages | Usually a library |
| Loading untrusted input | Parsing only builds data | Some loaders can build arbitrary objects |
Comments are the main reason people choose YAML
Config files collect knowledge: the reason a timeout is that long, or why a feature flag is off in staging. YAML lets you write that next to the value with a #. JSON doesn't. RFC 8259, the JSON standard, has no comment syntax at all, and the only things it allows between tokens are four whitespace characters: space, horizontal tab, line feed and carriage return. I covered the workarounds (JSONC, JSON5, "_comment" keys) in Can JSON have comments?.
Most JSON-vs-YAML arguments are really this one. Nobody misses comments in a file that a build tool regenerates every time. Everybody misses them in a hand-tuned deploy config.
YAML's type guessing is the main reason people regret it
YAML doesn't make you quote strings, so the parser has to guess what each unquoted value is. The old YAML 1.1 boolean type accepts 22 spellings: y, Y, yes, Yes, YES, n, N, no, No, NO, plus the true/false and on/off families in three cases each.
Hence the "Norway problem". Take a list of country codes:
countries:
- GB
- SE
- NO
On a parser that follows YAML 1.1, NO isn't the string "NO". As InfoWorld puts it, it becomes a boolean that evaluates to false. The same thing bites on/off feature switches and single-letter answers like y. The fix is to quote the value (- "NO"), and InfoWorld suggests a linter that forbids truthy values like YES or off so nobody has to remember.
YAML 1.2 cut that list down, and the YAML 1.2.2 spec says its primary focus was making YAML a strict superset of JSON. Which version you get depends on the library. js-yaml, for example, describes itself as a YAML 1.2 parser that also supports YAML 1.1. Check what your parser does before you trust an unquoted no.
JSON has no such problem. A string is always in double quotes (see why JSON requires double quotes), and RFC 8259 says the literal names true, false and null must be lowercase.
Whitespace: invisible in JSON, structural in YAML
In JSON, indentation is decoration. Minify a file to one line and it means the same thing.
In YAML, indentation is the structure. Move a key two spaces left and it belongs to a different parent, and the file may still parse. The spec also says tab characters must not be used in indentation, "since different systems treat tabs differently". A tab pasted from a chat message is a common way to break a YAML file that looked fine in the editor.
JSON fails loudly, on punctuation. A missing comma or a trailing one stops the parser (why trailing commas aren't allowed). Annoying while you type, but you never ship a JSON file that silently means something else.
Your tool may already have decided
Check what the consumer accepts first. npm's documentation says package.json "must be actual JSON, not just a JavaScript object literal", so that one is settled. Many CI systems and deployment tools only read YAML. When the tool picks the format, use it and put the effort into validation.
Because YAML 1.2 is built to be a superset of JSON, a YAML-only tool will usually accept a JSON file too. Ingy döt Net wrote in a 2025 post that "as far as we (the current core YAML dev team) know", JSON is fully a subset of YAML, and called it "more of a happy accident than something that was planned". That makes JSON a reasonable choice for generated input to YAML tools.
Security: loading untrusted config
When a config file can come from someone you don't trust (a user upload, a pull request from a fork), the loader matters more than the format. The PyYAML docs are blunt: "It is not safe to call yaml.load with any data received from an untrusted source", because it "is as powerful as pickle.load and so may call any Python function". Use yaml.safe_load, which "recognizes only standard YAML tags and cannot construct an arbitrary Python object". A JSON parser just builds lists, maps, strings, numbers and booleans, so there is less to get wrong.
Who should pick which
Pick YAML when people edit the file by hand and need to leave notes in it, or when it's deeply nested and JSON's braces would bury the values.
Pick JSON when:
- a program generates or rewrites the file;
- several languages read it and must get identical results;
- the input might be untrusted and you want the simplest possible parser.
My take: use YAML for anything a human maintains, and treat it like code. Quote every string that isn't obviously a string, and run a linter in CI. YAML without those two habits is where the horror stories come from. For anything generated, write JSON, even when the consumer reads YAML.
Converting between them
Since valid JSON is valid YAML 1.2, going from JSON to YAML mostly means removing braces and quotes. The JSON to YAML converter on this site does that in the browser, with no sign-up. The limitation: no converter can write the comments that justify each value, and those comments are the reason you switched. You still write them yourself.
Going the other way loses information. YAML comments, anchors and custom tags have no JSON equivalent, so check the output before you replace a hand-written YAML file with converted JSON.
FAQ
Is YAML better than JSON for config files?
For config that people edit by hand, usually yes: YAML allows # comments and needs less punctuation. For config that programs generate or that a tool requires as JSON, such as package.json, JSON is the better choice.
Is every JSON file valid YAML?
Under YAML 1.2, yes in practice. The spec says its primary focus was making YAML a strict superset of JSON, and the YAML core team wrote in 2025 that, as far as they know, JSON is fully a subset of YAML.
Why does YAML turn NO into false?
YAML 1.1 treats 22 spellings, including no, NO, off and y, as booleans. Parsers that still follow YAML 1.1 read an unquoted NO as false. Quote the value ("NO") to keep it a string.
Is it safe to load YAML from an untrusted source?
Only with a safe loader. PyYAML's own docs say it is not safe to call yaml.load on untrusted data because it can call any Python function; use yaml.safe_load instead.
Sources
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format
- YAML Ain't Markup Language (YAML) version 1.2.2
- Boolean Language-Independent Type for YAML Version 1.1
- Is JSON really a subset of YAML? (Ingy döt Net, 2025)
- PyYAML Documentation
- js-yaml on GitHub
- npm Docs: package.json
- 7 YAML gotchas to avoid, and how to avoid them (InfoWorld)