Aller au contenu

jq Cheatsheet - Command-line JSON Processor

jq Cheatsheet - Command-line JSON Processor

Installation

PlatformCommand
Ubuntu/Debiansudo apt-get update && sudo apt-get install jq
RHEL/CentOS/Fedorasudo yum install jq or sudo dnf install jq
Arch Linuxsudo pacman -S jq
macOS (Homebrew)brew install jq
macOS (MacPorts)sudo port install jq
Windows (Chocolatey)choco install jq
Windows (Scoop)scoop install jq
Dockerdocker run --rm -i stedolan/jq
Verify Installationjq --version

Basic Commands

CommandDescription
jq '.'Pretty-print JSON (identity filter)
jq '.fieldname'Extract specific field value
jq '.field1, .field2'Extract multiple fields
jq '.parent.child'Extract nested field value
jq '.[0]'Get first element of array
jq '.[1:3]'Array slice (elements 1-2)
jq '.[]'Iterate through all array elements
jq '.[].fieldname'Extract field from each array element
jq 'length'Get length of array or object
jq 'keys'Get all keys from object (sorted)
jq 'keys_unsorted'Get all keys in original order
jq 'values'Get all values from object
jq 'has("key")'Check if object has specific key
jq 'type'Get type of value (string, number, array, etc.)
jq -r '.field'Raw output (no quotes for strings)
jq -c '.'Compact output (no pretty-printing)
jq -S '.'Sort object keys in output
jq '.' file.jsonRead and process JSON from file
jq -n '{key: "value"}'Create JSON without input
jq 'empty'Produce no output

Advanced Usage

CommandDescription
`jq ’.[] \select(.age > 25)‘`
jq 'map(. * 2)'Apply operation to each array element
jq '{name: .firstName, age: .userAge}'Construct new object with renamed fields
jq 'if .age >= 18 then "adult" else "minor" end'Conditional logic
jq 'group_by(.category)'Group array elements by field value
jq 'sort'Sort array in ascending order
jq 'sort_by(.fieldname)'Sort array of objects by field
jq 'reverse'Reverse array order
jq 'unique'Get unique values from array
jq 'unique_by(.field)'Get unique objects by field value
jq 'reduce .[] as $item (0; . + $item)'Reduce array to single value (sum example)
`jq ’.. \numbers’`
jq '.field // "default"'Use default value if field is null/missing
jq 'try .field catch "error"'Error handling with fallback
jq 'flatten'Flatten nested arrays one level
jq 'flatten(2)'Flatten nested arrays N levels
jq '. + {newField: "value"}'Add or update fields
jq 'del(.fieldname)'Delete field from object
jq 'del(.[2])'Delete element from array by index
jq 'to_entries'Convert object to key-value pairs array
jq 'from_entries'Convert key-value pairs to object
`jq ‘with_entries(.value \= . * 2)‘`
`jq ’[.[] \select(.active)]‘`
jq 'min'Get minimum value from array
jq 'max'Get maximum value from array
jq 'min_by(.field)'Get object with minimum field value
jq 'max_by(.field)'Get object with maximum field value
jq 'add'Sum array of numbers or concatenate strings
jq 'any(. > 5)'Check if any element matches condition
jq 'all(. > 0)'Check if all elements match condition

String Operations

CommandDescription
jq '"Hello \(.name)"'String interpolation
`jq ‘.field \tostring’`
`jq ‘.field \tonumber’`
jq 'split("/")'Split string into array
jq 'join("-")'Join array elements into string
jq 'startswith("prefix")'Check if string starts with prefix
jq 'endswith("suffix")'Check if string ends with suffix
jq 'contains("substring")'Check if string contains substring
jq 'ltrimstr("prefix")'Remove prefix from string
jq 'rtrimstr("suffix")'Remove suffix from string
jq 'ascii_downcase'Convert string to lowercase
jq 'ascii_upcase'Convert string to uppercase
jq 'test("regex")'Test if string matches regex
jq 'match("regex")'Get regex match details
jq 'capture("(?<name>\\w+)")'Capture named regex groups
jq 'sub("old"; "new")'Replace first occurrence
jq 'gsub("old"; "new")'Replace all occurrences

Configuration

Command-Line Options

# Raw output (no JSON quotes for strings)
jq -r '.field' file.json

# Compact output (single line)
jq -c '.' file.json

# Sort object keys
jq -S '.' file.json

# Slurp mode (read entire input into array)
jq -s '.' file1.json file2.json

# Null input (don't read stdin)
jq -n '{created: now}'

# Exit status based on output
jq -e '.field' file.json  # Exit 1 if false/null

# Color output control
jq -C '.' file.json  # Force color
jq -M '.' file.json  # Disable color

# Custom indentation
jq --indent 4 '.' file.json
jq --tab '.' file.json

# Read filter from file
jq -f filter.jq data.json

# Pass variables to jq
jq --arg name "John" '{user: $name}' -n
jq --argjson count 42 '{total: $count}' -n
jq --slurpfile data file.json '{imported: $data}' -n

# Multiple inputs
jq --jsonargs '. | @json' --args arg1 arg2 arg3

Environment Variables

# Customize output colors (format: null:false:true:numbers:strings:arrays:objects)
export JQ_COLORS="0;90:0;91:0;92:0;93:0;94:0;95:0;96"

# Default colors (bright theme)
export JQ_COLORS="1;30:0;39:0;39:0;39:0;32:1;39:1;39"

# Disable colors entirely
export NO_COLOR=1

Filter Files

Create reusable filter files for complex operations:

# filter.jq
.data[]
| select(.status == "active")
| {
    id: .id,
    name: .name,
    created: .timestamp | strftime("%Y-%m-%d")
  }

# Usage
jq -f filter.jq data.json

Common Use Cases

Use Case: Parse API Response

# Extract specific fields from API response
curl -s https://api.example.com/users | jq '.users[] | {name: .name, email: .email}'

# Filter active users and get their IDs
curl -s https://api.example.com/users | jq -r '.users[] | select(.active == true) | .id'

# Count total results
curl -s https://api.example.com/users | jq '.users | length'

Use Case: Process AWS CLI Output

# List EC2 instance IDs and names
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | "\(.InstanceId) \(.Tags[]|select(.Key=="Name")|.Value)"'

# Get S3 bucket sizes
aws s3api list-buckets | jq -r '.Buckets[].Name' | while read bucket; do
  aws s3 ls s3://$bucket --recursive --summarize | grep "Total Size" | jq -R ". | {bucket: \"$bucket\", size: .}"
done

# Filter running instances
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(.State.Name == "running")'

Use Case: Log Analysis

# Parse JSON logs and extract errors
cat application.log | jq -r 'select(.level == "ERROR") | "\(.timestamp) \(.message)"'

# Count log entries by level
cat application.log | jq -s 'group_by(.level) | map({level: .[0].level, count: length})'

# Find slow requests (response time > 1000ms)
cat access.log | jq 'select(.response_time > 1000) | {path: .path, time: .response_time}'

Use Case: Transform Data Structure

# Convert flat structure to nested
echo '[{"id":1,"name":"John","dept":"IT"},{"id":2,"name":"Jane","dept":"HR"}]' | \
jq 'group_by(.dept) | map({department: .[0].dept, employees: map({id: .id, name: .name})})'

# Merge multiple JSON files
jq -s 'add' file1.json file2.json file3.json

# Create CSV from JSON
jq -r '.[] | [.id, .name, .email] | @csv' data.json

Use Case: Configuration Management

# Extract specific config value
jq -r '.database.host' config.json

# Update config value
jq '.database.port = 5432' config.json > config.tmp && mv config.tmp config.json

# Merge config files
jq -s '.[0] * .[1]' base-config.json override-config.json > final-config.json

# Validate required fields exist
jq -e '.database.host and .database.port' config.json && echo "Valid" || echo "Invalid"

Best Practices

  • Use -r for scripts: When extracting values for shell scripts, use raw output to avoid quoted strings
  • Pipe efficiently: Chain operations with | instead of multiple jq calls for better performance
  • Test filters incrementally: Build complex filters step-by-step, testing each part with sample data
  • Handle missing fields: Use // operator or try-catch to provide defaults for optional fields
  • Use -e for validation: Set exit status based on output for reliable error handling in scripts
  • Store complex filters: Save reusable filters in .jq files and use -f option for maintainability
  • Quote properly: Single-quote jq filters in shell to prevent shell expansion of special characters
  • Use select before map: Filter data before transforming to improve performance on large datasets
  • Leverage --arg for safety: Pass external values as arguments instead of string interpolation to prevent injection
  • Profile large operations: Use --debug flag to understand filter execution and optimize bottlenecks

Troubleshooting

IssueSolution
parse error: Invalid numeric literalCheck JSON syntax - likely missing quotes around strings or trailing commas
jq: error: syntax errorVerify filter syntax - ensure proper pipe usage and bracket matching
Output shows null unexpectedlyField doesn’t exist - use .field // "default" or has("field") to check first
Cannot index array with stringTrying to access object field on array - use .[] to iterate or .[0] for specific index
Cannot iterate over nullInput is null or empty - use -n flag or check input source
Colors not showing in outputPipe to less -R or use jq -C to force color output
jq: command not foundInstall jq using package manager or download from https://jqlang.github.io/jq/
Very slow performance on large filesUse streaming parser with --stream or filter early in pipeline
Special characters breaking filterWrap entire filter in single quotes and escape internal single quotes with '\''
Need to process multiple JSON objects (not array)Use jq -s '.' to slurp into array or process line-by-line with jq -c
Error: break or continue outside loopThese keywords only work inside while/until loops - restructure logic
Memory issues with large datasetsUse streaming mode --stream or process in chunks with limit(n; .)

Quick Reference: Operators

OperatorDescriptionExample
.Identity / current valuejq '.'
.fieldObject field accessjq '.name'
.[n]Array index accessjq '.[0]'
.[]Array/object iterationjq '.[]'
`\`Pipe (chain operations)
,Multiple outputsjq '.a, .b'
//Alternative operatorjq '.field // "default"'
?Optional operator (suppress errors)jq '.field?'
+Addition / concatenationjq '.a + .b'
-Subtraction / array differencejq '.a - .b'
*Multiplication / object mergejq '. * {new: "field"}'
/Divisionjq '.total / .count'
%Modulojq '. % 2'
==Equalityjq '.a == .b'
!=Inequalityjq '.a != .b'
<, <=, >, >=Comparisonsjq '.age > 18'