JSON / jq Dev Config Cheatsheet
This cheatsheet covers common jq command-line JSON operations: key access, array filtering, object manipulation, pipe chaining, and built-in functions for efficient JSON processing in shell scripts.
Basic Operations (jq-basic)
``bash
# Pretty-print JSON
cat data.json | jq '.'
# Extract root key cat data.json | jq '.name'
# Extract nested key cat data.json | jq '.address.city'
# Optional operator (no error if key missing) cat data.json | jq '.name?'
# Extract multiple keys cat data.json | jq '{name, email}'
# Comma operator (multiple expressions) cat data.json | jq '.name, .age'
# Pipe to another jq cat data.json | jq '.users' | jq '.[]'
# Raw output (strip quotes) cat data.json | jq -r '.name'
# Compact output (no newlines/indent) cat data.json | jq -c '.'
# Read from stdin
echo '{"a": 1}' | jq '.a'
`
Filtering (jq-filter)
`bash
# Array expansion
cat data.json | jq '.users[]'
# Conditional filter cat data.json | jq '.users[] | select(.age > 18)'
# Multiple conditions (AND) cat data.json | jq '.users[] | select(.age > 18 and .city == "Beijing")'
# Multiple conditions (OR) cat data.json | jq '.users[] | select(.age > 60 or .role == "admin")'
# Negation cat data.json | jq '.users[] | select(.age < 18 | not)'
# Inclusion check cat data.json | jq '.users[] | select(.tags | index("vip"))'
# Custom range filter cat data.json | jq '[.[] | select(.price > 10 and .price < 100)]'
# Null/non-null filter cat data.json | jq '.users[] | select(.email != null)'
# String pattern match cat data.json | jq '.users[] | select(.name | test("^A.*"))'
# Regex test
cat data.json | jq '.users[] | select(.phone | test("^1[3-9]\\d{9}$"))'
`
Array Operations (jq-array)
`bash
# Array length
cat data.json | jq '.users | length'
# First / last element cat data.json | jq '.users[0]' cat data.json | jq '.users[-1]'
# Array slicing cat data.json | jq '.users[0:3]' # first 3 cat data.json | jq '.users[2:5]' # 3rd-5th cat data.json | jq '.users[:2]' # first 2
# Flatten array cat data.json | jq '[.. | objects | .name?]'
# Unique values cat data.json | jq '[.users[].city] | unique'
# Sort by key cat data.json | jq '.users | sort_by(.age)'
# Reverse sort cat data.json | jq '.users | sort_by(.age) | reverse'
# Append element cat data.json | jq '.users + [{name: "New"}]'
# Min / max cat data.json | jq '[.users[].age] | min' cat data.json | jq '[.users[].age] | max'
# Array map
cat data.json | jq '[.users[] | {name, age, adult: (.age >= 18)}]'
`
Object Operations (jq-object)
`bash
# Select specific fields
cat data.json | jq '.users[] | {name, email}'
# Rename fields cat data.json | jq '.users[] | {user_name: .name, user_age: .age}'
# Add fields cat data.json | jq '.users[] | . + {active: true}'
# Delete fields cat data.json | jq 'del(.users[].password)'
# Merge objects cat data.json | jq '.user1 * .user2'
# Convert entries to object cat data.json | jq '.users | from_entries'
# Convert object to entries cat data.json | jq '.users | to_entries'
# Get all keys cat data.json | jq '.users[0] | keys'
# Check key existence cat data.json | jq '.users[0] | has("email")'
# Key-value pairs cat data.json | jq '.users[0] | to_entries[] | "\\(.key): \\(.value)"'
# Keep only non-null fields
cat data.json | jq '.users[] | with_entries(select(.value != null))'
`
Pipes & Compositions (jq-pipe)
`bash
# Chained pipe
cat data.json | jq '.users | sort_by(.age) | reverse | .[0:3]'
# Group by key cat data.json | jq '.users | group_by(.city)'
# Group then count cat data.json | jq '.users | group_by(.city) | map({city: .[0].city, count: length})'
# Group then aggregate cat data.json | jq '.users | group_by(.city) | map({city: .[0].city, total_age: map(.age) | add})'
# Slurp mode (read multi-line JSON as array) cat data.json | jq -s '. | length'
# Slurp then group cat data.json | jq -s 'group_by(.type) | map({type: .[0].type, count: length})'
# Pass shell variable with --arg city="Beijing" cat data.json | jq --arg city "$city" '.users[] | select(.city == $city)'
# Pass JSON value with --argjson cat data.json | jq --argjson min 18 '.users[] | select(.age >= $min)'
# Read file content with --rawfile cat data.json | jq --rawfile tmpl template.txt '.message = $tmpl'
# Define function
cat data.json | jq 'def double: . * 2; [.users[].age | double]'
`
Built-in Functions (jq-builtin)
`bash
# length - string/array/object length
cat data.json | jq '.name | length'
cat data.json | jq '.users | length'
# keys - object key list cat data.json | jq 'keys'
# has - key existence check cat data.json | jq 'has("users")'
# select - conditional filter cat data.json | jq '.users[] | select(.age > 18)'
# map - transform each element cat data.json | jq '[.users[] | map(.name)]'
# add - sum array cat data.json | jq '[.users[].age] | add'
# join - join array into string cat data.json | jq '[.users[].name] | join(", ")'
# split - split string cat data.json | jq -r '.names | split(", ")'
# unique - deduplicate and sort cat data.json | jq '[.users[].city] | unique'
# sort - sort array cat data.json | jq '[.users[].age] | sort'
# range - generate number sequence cat data.json | jq '[range(5)]'
# floor / sqrt cat data.json | jq '[.users[].score | floor]' cat data.json | jq '[.users[].score | sqrt]'
# tostring / tonumber cat data.json | jq '.users[].age | tostring' echo '"42"' | jq 'tonumber'
# type - return type name cat data.json | jq '.users | type'
# Null coalescing cat data.json | jq '.missing // "default_value"'
# empty - return nothing (for filtering) cat data.json | jq '.users[] | select(.age > 100) | (.name, empty)'
# error - throw an error
cat data.json | jq 'if .users == null then error("no users") else . end'
`
jq CLI Options Reference
`bash
# Common options
jq '.' data.json # format file
jq -c '.' data.json # compact output
jq -r '.name' data.json # raw output (no quotes)
jq -n '{"a": 1}' # build JSON from scratch
jq -s '.' *.json # slurp mode: merge files
jq --arg k v '.[$k]' # pass arguments
jq --argjson k 42 '.[$k]' # pass JSON argument
jq -f script.jq data.json # read filter from file
``
Basic Ops(8)
| Command | Level | ||
|---|---|---|---|
jq '.' data.jsonPretty-print JSON | Basic | jq '.' data.json | |
jq '.address.city'Extract nested key value | Basic | cat data.json | jq '.address.city' | |
jq '.name?'Optional operator, no error if key missing | Basic | cat data.json | jq '.name?' | |
jq '{name, email}'Extract multiple keys | Basic | cat data.json | jq '{name, email}' | |
jq '.name, .age'Comma operator (multiple expressions) | Intermediate | cat data.json | jq '.name, .age' | |
jq -r '.name'Raw output (strip quotes from strings) | Basic | cat data.json | jq -r '.name' | |
jq -c '.'Compact output (single line, no indent) | Basic | cat data.json | jq -c '.' | |
jq -f script.jq data.jsonRead jq filter from file | Intermediate | jq -f script.jq data.json |
Filtering(5)
| Command | Level | ||
|---|---|---|---|
jq '.users[]'Expand array into individual elements | Basic | cat data.json | jq '.users[]' | |
jq '.users[] | select(.age > 18)'Filter array elements by condition | Intermediate | cat data.json | jq '.users[] | select(.age > 18)' | |
jq '.users[] | select(.age > 18 and .city == "Beijing")'Multiple conditions with AND | Intermediate | cat data.json | jq '.users[] | select(.age > 18 and .city == "Beijing")' | |
jq '.users[] | select(.age > 60 or .role == "admin")'Multiple conditions with OR | Intermediate | cat data.json | jq '.users[] | select(.age > 60 or .role == "admin")' | |
jq '.users[] | select(.name | test("^A.*"))'Regex pattern match filter | Expert | cat data.json | jq '.users[] | select(.name | test("^A.*"))' |
Arrays(6)
| Command | Level | ||
|---|---|---|---|
jq '.users | length'Get array length | Basic | cat data.json | jq '.users | length' | |
jq '.users[0]'Get first array element | Basic | cat data.json | jq '.users[0]' | |
jq '.users[-1]'Get last array element | Basic | cat data.json | jq '.users[-1]' | |
jq '.users[0:3]'Array slice (first 3 elements) | Intermediate | cat data.json | jq '.users[0:3]' | |
jq '.users | sort_by(.age)'Sort by field | Intermediate | cat data.json | jq '.users | sort_by(.age)' | |
jq '[.users[].city] | unique'Deduplicate and sort array | Intermediate | cat data.json | jq '[.users[].city] | unique' |
Objects(6)
| Command | Level | ||
|---|---|---|---|
jq '.users[] | {name, email}'Select specific fields from object | Basic | cat data.json | jq '.users[] | {name, email}' | |
jq '.users[] | {user_name: .name, user_age: .age}'Rename object fields | Intermediate | cat data.json | jq '.users[] | {user_name: .name, user_age: .age}' | |
jq '.users[] | . + {active: true}'Add field to object | Intermediate | cat data.json | jq '.users[] | . + {active: true}' | |
jq 'del(.users[].password)'Delete object field | Intermediate | cat data.json | jq 'del(.users[].password)' | |
jq '.users[0] | keys'Get all keys of an object | Basic | cat data.json | jq '.users[0] | keys' | |
jq '.users[0] | has("email")'Check if key exists | Basic | cat data.json | jq '.users[0] | has("email")' |
Pipes(4)
| Command | Level | ||
|---|---|---|---|
jq -s '.'Slurp mode — read multi-line JSON as array | Intermediate | cat data.json | jq -s '.' | |
jq --arg city "Beijing" '.users[] | select(.city == $city)'Pass shell variable to jq with --arg | Intermediate | jq --arg city "Beijing" '.users[] | select(.city == $city)' | |
jq --argjson min 18 '.users[] | select(.age >= $min)'Pass JSON value with --argjson | Expert | jq --argjson min 18 '.users[] | select(.age >= $min)' | |
jq '.users | group_by(.city)'Group by field | Expert | cat data.json | jq '.users | group_by(.city)' |
Built-in(4)
| Command | Level | ||
|---|---|---|---|
jq '[.users[].name] | join(", ")'join — concatenate array into string | Intermediate | cat data.json | jq '[.users[].name] | join(", ")' | |
jq '[.users[].age] | add'add — sum array elements | Intermediate | cat data.json | jq '[.users[].age] | add' | |
jq '.missing // "default"'Null coalescing operator with default | Intermediate | cat data.json | jq '.missing // "default"' | |
jq -n '{"a": 1}'Create JSON from scratch with -n flag | Basic | jq -n '{"a": 1}' |