| name | parsing-json |
| description | Use when parsing, querying, transforming, or extracting data from JSON files, API responses, or JSON streams. Always use the `jq` CLI for all JSON operations. Do not use for YAML, XML, CSV, or plain-text parsing. Never build JSON from scratch in Python, Node, or other languages when `jq` can handle it. |
| compatibility | Requires `jq` 1.6+ installed |
| license | MIT |
| metadata | {"author":"Robert Hafner","source":"https://github.com/tedivm/opencode-config"} |
Quick start
All JSON processing must use jq. Never write custom scripts in Python, Node,
Ruby, sed, awk, or grep for JSON manipulation. jq handles every common
pattern cleanly.
jq . file.json
jq -r '.users[0].name' file.json
jq '.items[] | select(.active)' file.json
jq -r '[.id, .name, .email] | @csv' file.json
Pipe data from curl or other commands directly into jq:
curl -s 'https://api.example.com/users' | jq '.[] | {name, email}'
curl -s 'https://api.example.com/status' | jq -r '.version'
curl -s 'https://api.example.com/items' | jq '[.[] | select(.active)] | length'
curl -s 'https://api.example.com/files' | jq -r '.[] | "wget \(.url)"'
curl -s 'https://api.example.com/data' | jq -c '.[]' | while read -r line; do
echo "$line"
done
Golden rules
-
Always use jq. If the task involves reading, querying, transforming,
or writing JSON, use jq. No exceptions for Python, Node, sed, awk,
or custom scripts.
-
Quote jq filters with single quotes. Prevents shell interpolation
conflicts: jq '.field' not jq .field.
-
Use -r (raw output) for plain text. Without -r, strings are
quoted in output. Use -r when piping to other commands, writing to
files, or generating non-JSON output.
-
Use -c (compact) for machine-readable output. Piping JSON to
another jq call or another JSON consumer? Use -c.
-
Use --arg for injecting shell variables. Never use string
interpolation to inject values into jq filters.
jq --arg id "$ID" 'select(.id == $id)' file.json
jq "select(.id == \"$ID\")" file.json
-
Use --argjson for passing JSON values. When the variable is
already valid JSON (numbers, booleans, arrays, objects).
jq --argjson config "$CONFIG_JSON" '. + $config' file.json
Advanced patterns
Shell variable injection (never interpolate)
jq --arg id "$ID" --arg env "$ENV" 'select(.id == $id and .env == $env)' file.json
jq --argjson limit "$LIMIT" --argjson flags "$FLAGS_JSON" '.items[:$limit] | map(. + $flags)' file.json
jq --slurpfile config config.json '. + $config[0]' file.json
jq --rawfile readme README.md '.docs = $readme' file.json
Aggregations and reductions
jq 'group_by(.status) | map({status: .[0].status, count: length})' file.json
jq 'group_by(.category) | map({category: .[0].category, total: (map(.price) | add)})' file.json
jq 'reduce .[] as $item (0; if $item.active then . + 1 else . end)' file.json
Object/array transformations
jq -s '.[0] * .[1]' base.json overrides.json
jq '[.[] | .newKey = .oldKey | del(.oldKey)]' file.json
jq 'reduce .[] as $item ({}; .[$item.id] = $item)' file.json
jq '[.[][]]' file.json
jq 'unique_by(.id)' file.json
String extraction and generation
jq -r '.[] | "curl -s \(.url)"' file.json
jq -r '.[] | .path | capture("(?<dir>/[^/]+)/(?<file>[^/]+)")' file.json
jq -r '"id,name,email"; (.[] | [.id, .name, .email] | @csv)' file.json
jq -r '.data | @base64' file.json
echo "data" | jq -Rr '@base64d'
Streaming large files
jq --stream 'select(.[0] == "items" and .[1] | test("^item"))' large.json
jq -c 'select(.active)' file.ndjson
Error handling and robustness
jq -r '.user.name // "unknown"' file.json
jq -r 'try .data.results[].id catch empty' file.json
jq -e '.' file.json || echo "Invalid JSON"
Multi-file workflows
jq -s '.' file1.json file2.json
jq -s '[.[][] | select(.active)] | length' data/*.json
jq -s 'reduce .[] as $item ({}; . * $item)' templates/*.json
Advanced features
Installing jq: See references/installation.md