DevOps Tutorial · Linux and the Shell · Lesson 10 of 25
Working with JSON and YAML
Read and transform JSON with jq, and write YAML for CI pipelines and Kubernetes without the classic mistakes.
JSON with jq
Cloud CLIs and APIs return JSON; jq extracts what you need:
cat > instances.json <<'JSON'
{"instances": [
{"id": "i-01", "state": "running", "tags": {"team": "payments"}},
{"id": "i-02", "state": "stopped", "tags": {"team": "search"}},
{"id": "i-03", "state": "running", "tags": {"team": "search"}}
]}
JSON
echo "running instances:"
jq -r '.instances[] | select(.state == "running") | .id' instances.json
echo "count per team:"
jq -c '[.instances[].tags.team] | group_by(.) | map({team: .[0], count: length})' instances.json
Output
running instances:
i-01
i-03
count per team:
[{"team":"payments","count":1},{"team":"search","count":2}]Run this on your computer — see “Get Started” for setup.
Combine with the AWS CLI: aws ec2 describe-instances | jq -r '.Reservations[].Instances[].InstanceId' (the AWS
CLI also has its own --query option).
YAML
CI pipelines (GitHub Actions, GitLab CI), Kubernetes manifests, Docker Compose and Ansible use YAML: nested
keys by indentation, lists with -.
service: api
replicas: 3
ports:
- 8080
- 9090
env:
LOG_LEVEL: info
FEATURE_X: "on" # quote it: unquoted on/off/yes/no can become booleans in YAML 1.1 parsers
Classic YAML mistakes:
- Indentation with tabs (not allowed) or one space off, which silently changes structure.
- Unquoted special values:
no,on,08,1.10may become booleans, octal-ish numbers or1.1. - Copy-pasted duplicate keys: the last one silently wins in many parsers.
import json
# A YAML 1.1 parser (like PyYAML) reads these unquoted values as:
yaml_11 = {"country": "no", "enabled": "on", "version": "1.10"}
parsed = {"country": False, "enabled": True, "version": 1.1}
for key, text in yaml_11.items():
print(f"{key}: {text:5} -> {json.dumps(parsed[key])}")
print("quote strings that look like booleans or numbers: version: \"1.10\"")
Output
country: no -> false enabled: on -> true version: 1.10 -> 1.1 quote strings that look like booleans or numbers: version: "1.10"
Test yourself
Which jq filter prints the id of each item in an array called items?
.items[].iditems.id$.items.id.id[]
Show answer
Answer: .items[].id
.items[] iterates the array and .id picks the field from each element.