JSON vs YAML for Configuration Files

By Sheng Pang · Published · 3 min read

If you have written a Docker Compose file, a GitHub Actions workflow or a Kubernetes manifest, you have written YAML. If you have edited package.json or tsconfig.json, you have written JSON. Both describe the same kinds of data. The difference is in how forgiving they are to write and how forgiving they are to read back.

The same config in both

{
  "server": {
    "port": 8080,
    "hosts": ["api.example.com", "www.example.com"],
    "tls": true
  },
  "logLevel": "info"
}
server:
  port: 8080
  hosts:
    - api.example.com
    - www.example.com
  tls: true
logLevel: info   # can be debug, info, warn, error

YAML drops the braces, the quotes and most of the commas, and it allows the comment on the last line. For a human typing a config file that is a real improvement.

Where YAML wins

  • Comments. Config files need them and JSON has none.
  • Less punctuation. No quotes on simple strings, no commas, no braces. Fewer chances to mistype.
  • Multi line strings. The | and > block indicators let you paste a script or a paragraph without escaping every new line.
  • Anchors and aliases. Define a block once and reuse it with &name and *name. Useful for repeated job definitions in CI files.
  • Multiple documents in one file, separated by ---. Kubernetes relies on this.

Where JSON wins

  • One way to write everything. YAML has several syntaxes for strings, lists and maps. JSON has one, so files from different people look the same.
  • Whitespace does not matter. A YAML file breaks if one line is indented two spaces instead of four. JSON does not care.
  • No surprise type conversion. See the gotchas below.
  • Every language parses it identically. YAML parsers differ in which version of the spec they follow and in edge case behaviour.
  • Machine generated output. If a program writes the file and a program reads it, YAML's readability buys nothing and its complexity costs.

The YAML gotchas

YAML tries to guess the type of an unquoted value. That guessing produces the format's most famous bugs.

country: NO        # becomes the boolean false in YAML 1.1
version: 1.10      # becomes the number 1.1
time: 12:30        # becomes the integer 750 in YAML 1.1 (sexagesimal)
zip: 01234         # becomes 668 (octal) in some parsers
answer: yes        # becomes true

The first one is known as the Norway problem because the country code NO turns into false. YAML 1.2 fixed most of these, but many parsers, including the widely used PyYAML, still default to 1.1 behaviour. The safe habit is to quote any string that could look like something else.

Indentation is the other trap. Tabs are not allowed. A list nested under a key must be indented consistently, and the error messages when it is not are often unhelpful.

YAML is a superset of JSON

Almost every valid JSON document is also valid YAML, because YAML accepts the brace and bracket flow style. That means you can paste a JSON block into a YAML file when you need precision, and you can convert YAML to JSON to check what a parser actually sees. If a YAML file is behaving oddly, converting it and reading the result in our JSON formatter often reveals the mistake.

Recommendation

SituationUse
Hand written config that people edit oftenYAML, quote anything ambiguous
Config the tool already dictatesWhatever the tool wants
Machine generated or machine consumed dataJSON
API payloadsJSON, always
Small config with no comments neededJSON
Need comments but want JSON strictnessJSON5 or JSONC if your tool supports them

← Back to all articles