// Query. Transform. Extract.
JSON IS EVERYWHERE.
APIs return JSON. Config files are JSON. NoSQL databases speak JSON. jq is your power tool for querying and transforming JSON data from the command line.
JSON AT SPEED.
Why write a Python script when jq can extract exactly what you need in one line? Filter complex JSON structures, reshape data, and build pipelines—all at terminal speed.
Click a lesson to begin
What is jq? Installation and basics.
BeginnerIdentity, object, and array access.
BeginnerKeys, values, and dot notation.
BeginnerIndices, slices, and iteration.
BeginnerChain jq filters together.
BeginnerCreate arrays and objects.
Intermediateif-then-else and comparisons.
Intermediatemap, select, flatten, and more.
IntermediateString operations and interpolation.
Intermediatecurl, jq, and REST APIs.
AdvancedBinding and using variables.
AdvancedAutomate jq in bash scripts.
Advancedjq is a lightweight command-line JSON processor. It lets you filter, transform, and extract data from JSON with a powerful, expressive syntax.
# Debian/Ubuntu sudo apt install jq # macOS brew install jq # Check version jq --version
jq 'FILTER' [FILE...] echo 'JSON' | jq 'FILTER'
# Pretty print JSON
echo '{"name":"Alice","age":30}' | jq '.'
# Identity filter (.)
cat data.json | jq '.'
# Validate JSON
cat data.json | jq . > /dev/null && echo "Valid JSON"
1. What does jq do?
The dot (.) filter returns the entire input unchanged. It's the most basic jq filter.
# Identity - output same as input
echo '{"a":1,"b":2}' | jq '.'
# Array
echo '[1,2,3]' | jq '.'
# Nested
echo '{"user":{"name":"Bob"}}' | jq '.'
1. What does the identity filter (.) return?
Access object properties with dot notation: `.key`
# Access property
echo '{"name":"Alice","age":30}' | jq '.name'
# Nested access
echo '{"user":{"name":"Bob","email":"bob@example.com"}}' | jq '.user.email'
# Multiple properties
echo '{"name":"Alice","age":30}' | jq '.name, .age'
# Optional: ? for missing keys
echo '{"name":"Alice"}' | jq '.age?'
# Bracket notation (useful for special chars)
echo '{"user-name":"Alice"}' | jq '.["user-name"]'
# Keys with spaces
echo '{"first name":"Alice"}' | jq '.["first name"]'
1. How do you access a nested property in jq?
# First element echo '[10,20,30]' | jq '.[0]' # Last element echo '[10,20,30]' | jq '.[-1]' # Second element echo '[10,20,30]' | jq '.[1]' # Array length echo '[10,20,30]' | jq 'length'
# First two elements echo '[10,20,30,40]' | jq '.[:2]' # Elements 1-3 (indices 1, 2, 3) echo '[10,20,30,40]' | jq '.[1:4]' # Last two elements echo '[10,20,30,40]' | jq '.[-2:]'
1. How do you access the last element of an array?
The pipe (|) passes output of one filter as input to the next, just like shell pipes.
# Get array, then first element
echo '{"items":[10,20,30]}' | jq '.items | .[0]'
# Shorthand
echo '{"items":[10,20,30]}' | jq '.items[0]'
# Chain multiple
echo '{"user":{"name":"Alice","posts":[{"title":"Hello"}]}}' | jq '.user.posts[0].title'
# Get all titles
echo '{"posts":[{"title":"A"},{"title":"B"}]}' | jq '.posts[].title'
# Recursively descend
echo '{"a":{"b":{"c":1}}}' | jq '..'
# Find all objects with key
echo '{"name":"Alice"}' | jq '.. | objects'
1. What does the pipe operator (|) do in jq?
# Object construction
echo '{}' | jq '{name: "Alice", age: 30}'
# From input
echo '{"first":"John","last":"Doe"}' | jq '{fullname: .first, last: .last}'
# With computed values
echo '{"name":"Alice","age":30}' | jq '{name: .name, adult: .age >= 18}'
# Array construction
echo '[]' | jq '[.a, .b, .c]'
# From array
echo '[1,2,3]' | jq '[.[] | . * 2]'
# Collecting
echo '{"items":[1,2,3]}' | jq '[.items[] | select(. > 1)]'
1. How do you create an object with computed values?
# Basic if
echo '{"age":25}' | jq 'if .age >= 18 then "adult" else "minor" end'
# Multiple conditions
echo '{"score":85}' | jq 'if .score >= 90 then "A" elif .score >= 80 then "B" else "C" end'
== Equal != Not equal < > Less, greater <= >= Less or equal, greater or equal and Boolean AND or Boolean OR not Boolean NOT
1. What is the jq if-then-else syntax?
map(FILTER) Apply filter to each element select(COND) Keep elements matching condition flatten Flatten nested arrays unique Remove duplicates sort Sort arrays keys Get object keys values Get object values type Get value type
# Double each element
echo '[1,2,3]' | jq 'map(. * 2)'
# Select adults
echo '[{"age":10},{"age":25},{"age":17}]' | jq 'map(select(.age >= 18))'
# Get keys
echo '{"a":1,"b":2}' | jq 'keys'
# Unique and sort
echo '[3,1,2,3,1]' | jq 'unique | sort'
1. What function filters array elements?
+ Concatenate strings * Repeat string split(S) Split into array join(S) Join array with separator ascii_downcase lowercase ascii_upcase UPPERCASE ltrimstr(S) Remove prefix rtrimstr(S) Remove suffix
# Concatenate
echo '"Hello"' | jq '. + " World"'
# Uppercase
echo '"hello"' | jq 'ascii_upcase'
# Split
echo '"a,b,c"' | jq 'split(",")'
# String interpolation with +
echo '{"name":"Alice"}' | jq '"Hello, " + .name'
1. How do you convert a string to uppercase?
Query APIs and extract exactly what you need with curl piped to jq.
# GitHub API - get repo stars
curl -s api.github.com/repos/torvalds/linux | jq '.stargazers_count'
# Get all repo names
curl -s api.github.com/users/torvalds/repos | jq '.[].name'
# Get user's followers
curl -s api.github.com/users/torvalds | jq '{login, followers, public_repos}'
# Weather API (example)
curl -s wttr.in/London.json | jq '{temp: .current_condition.temp_C, condition: .current_condition.weatherDesc[0].value}'
# Docker stats JSON
docker stats --no-stream --format '{{json .}}' | jq '{name: .Name, cpu: .CPUPerc, mem: .MemPerc}'
1. What command fetches JSON from an API?
# Assign to variable
echo '{"name":"Alice"}' | jq '.name as $name | "Hello \($name)"'
# Multiple variables
echo '{"first":"John","last":"Doe"}' | jq '.first as $f | .last as $l | "\($f) \($l)"'
# Define constant echo '5' | jq 'let $x = 10; . + $x'
1. How do you use a variable in jq string interpolation?
#!/bin/bash
# Fetch and parse API data
USERNAME="torvalds"
REPOS=$(curl -s "https://api.github.com/users/$USERNAME/repos" | jq -r '.[].name')
echo "Repos for $USERNAME:"
for repo in $REPOS; do
stars=$(curl -s "https://api.github.com/repos/$USERNAME/$repo" | jq '.stargazers_count')
echo " $repo: $stars stars"
done
#!/bin/bash
# Extract errors from JSON logs
jq -r 'select(.level=="error") | "\(.timestamp) \(.message)"' app.log.json > errors.txt
# Generate summary
jq '{errors: map(select(.level=="error")) | length, warnings: map(select(.level=="warning")) | length}' app.log.json
You've mastered jq! You now understand:
jq is essential for anyone working with APIs, configuration files, or any JSON data. It replaces complex Python or JavaScript scripts with elegant one-liners.
Master jq and you'll extract exactly what you need from any JSON data in seconds.
Query. Transform. Extract.