JSON and YAML¶
7-minute read. Assumes you've read Terminal basics.
Why this page exists¶
Almost every configuration file, API response, and infrastructure definition you will meet is JSON or YAML. They describe the same kinds of data in different syntax, and most of the frustration people have with them comes from three or four specific gotchas rather than from the formats being hard.
The shapes¶
Both formats build everything from four things:
- Scalars: a string, number, boolean, or null
- Lists (arrays): an ordered sequence
- Maps (objects, dictionaries): named keys with values
- Nesting: lists and maps containing more lists and maps
That is the whole data model. Once you can see those four in a file, the syntax is just punctuation.
JSON¶
{
"name": "web-server",
"port": 8080,
"enabled": true,
"replicas": null,
"tags": ["production", "eu-west"],
"resources": {
"cpu": "500m",
"memory": "512Mi"
}
}
Rules that trip people up:
- Keys must be double-quoted strings. Single quotes are invalid.
- No trailing comma after the last item. This is the single most common JSON error.
- No comments. There is no comment syntax in JSON at all.
- Strings use double quotes; numbers,
true,false, andnullare bare.
JSON is strict and unambiguous, which makes it excellent for machines and slightly tedious for humans.
YAML¶
The same data:
name: web-server
port: 8080
enabled: true
replicas: null
tags:
- production
- eu-west
resources:
cpu: 500m
memory: 512Mi
Rules:
- Indentation defines structure, and it must be spaces, never tabs. A tab is a syntax error.
- A key-value pair is
key: value, with a space after the colon. - A list item starts with
-. - Comments start with
#. - Quotes are optional for most strings and required when the value would otherwise be parsed as something else.
YAML is a superset of JSON, so valid JSON is valid YAML. That is occasionally useful when you need to embed one in the other.
The YAML gotchas worth memorizing¶
1. Tabs are illegal. Configure your editor to insert spaces in .yaml files. Most "invalid YAML" errors on a file that looks fine are a stray tab.
2. Indentation must be consistent. Two spaces is conventional. What matters is that sibling keys line up exactly.
3. Some bare words are not strings.
version: 1.10 # the number 1.1, because trailing zeros are dropped
port: "8080" # a string
enabled: yes # older YAML parsers read this as boolean true
country: NO # Norway, or boolean false, depending on the parser
time: 12:30 # may parse as a sexagesimal number
The fix is always the same: quote it when you mean a string. version: "1.10" is unambiguous.
4. Multi-line strings have two forms:
literal: |
line one
line two
# keeps the newlines
folded: >
this is all
one long line
# newlines become spaces
5. A colon inside an unquoted value breaks parsing.
message: Error: something failed # invalid
message: "Error: something failed" # fine
Reading them from the terminal¶
jq for JSON and yq for YAML are worth installing on day one.
# Pretty-print and inspect
cat config.json | jq .
cat config.json | jq '.resources.cpu'
cat config.json | jq '.tags[]'
cat config.json | jq '.items[] | select(.status == "active") | .name'
# The same for YAML
yq '.resources.cpu' config.yaml
# Convert between them
yq -o json config.yaml
Validating before you deploy something saves a lot of time:
jq empty config.json # prints nothing if valid, an error if not
yq '.' config.yaml > /dev/null
python3 -c 'import json,sys; json.load(open("config.json"))'
Which format where¶
| You will see | Format |
|---|---|
| REST API requests and responses | JSON |
package.json, tsconfig.json | JSON |
| Kubernetes manifests | YAML |
| GitHub Actions workflows | YAML |
| Docker Compose | YAML |
| Ansible playbooks | YAML |
| CloudFormation | Either |
| Terraform | HCL, which is a third thing but reads similarly |
The rough rule: machines talk JSON to each other, humans write YAML for machines.
A note on YAML in the age of infrastructure as code¶
Because YAML has no types beyond the basics and no validation of its own, a manifest can be perfectly valid YAML and completely wrong for the system consuming it. That is why tools ship schemas and validators, and why editors with schema support for Kubernetes or GitHub Actions catch far more mistakes than a YAML linter alone.
Turn on schema validation in your editor. It is the single highest-value setup step for anyone writing these files daily.
Practice¶
cat > test.yaml <<'YAML'
service:
name: api
port: 8080
tags:
- web
- public
YAML
yq '.service.name' test.yaml
yq -o json test.yaml
yq -o json test.yaml | jq '.service.tags[]'
rm test.yaml
Then deliberately break it: add a tab, remove the space after a colon, add a trailing comma to the JSON output. Reading the resulting error messages is the fastest way to learn to recognize them later.
What to look at next¶
- HTTP and APIs - where the JSON you meet usually comes from
- What is an API call?
- Terminal basics
- Terraform explained - configuration as code
- Kubernetes in 10 minutes - the largest consumer of YAML you will meet