Working with JSON and APIs
Prerequisites: Pipes: connecting commands, Variables
Web APIs return JSON. Two tools make Bash good at working with them:
curl makes HTTP requests, and jq processes JSON. Install jq with
your package manager (apt install jq, brew install jq).
jq basics
# illustrative
json='{"name": "Ada", "languages": ["R", "Python"], "address": {"city": "London"}}'
echo "$json" | jq '.name'
echo "$json" | jq -r '.name'
echo "$json" | jq -r '.address.city'
echo "$json" | jq -r '.languages[]'
echo "$json" | jq '.languages | length'
"Ada"
Ada
London
R
Python
2
.keyselects a field;.a.bgoes deeper;.list[]outputs each array element.-rprints raw text without JSON quotes — what you want in scripts.|inside a jq program chains filters, just like shell pipes.
Filtering arrays
# illustrative
cat > users.json <<'EOF'
[
{"name": "Ada", "role": "admin", "active": true},
{"name": "Linus", "role": "dev", "active": false},
{"name": "Grace", "role": "admin", "active": true}
]
EOF
jq -r '.[] | select(.role == "admin") | .name' users.json
jq '[.[] | select(.active)] | length' users.json
jq -r '.[] | "\(.name) (\(.role))"' users.json
Ada
Grace
2
Ada (admin)
Linus (dev)
Grace (admin)
Paste JSON into the JSON Formatter to explore its structure before writing a jq filter.
Calling an API with curl
# illustrative
response=$(curl -fsS --max-time 10 \
-H "Accept: application/json" \
"https://api.github.com/repos/torvalds/linux") || {
echo "Request failed" >&2
exit 1
}
stars=$(jq -r '.stargazers_count' <<< "$response")
echo "Linux has $stars stars on GitHub"
-fmakes curl fail (non-zero exit) on HTTP errors like 404;-shides the progress bar;-Sstill shows errors.--max-timesets a timeout — always set one.-Hadds a header. For POST requests:curl -X POST -H "Content-Type: application/json" -d '{"title":"Hi"}' URL.
Secrets
Pass API tokens through environment variables, not command-line arguments
(which other users can see in ps), and never commit them:
curl -H "Authorization: Bearer $API_TOKEN" ....