Basics of jq
What is jq?
jq is a command-line tool for processing JSON.
It lets you:
- Read JSON
- Extract values
- Filter data
- Transform JSON
- Combine fields
- Convert JSON into other formats
Think of it as sed/awk for JSON.
Installation
Debian / Ubuntu
sudo apt install jq
Check:
jq --version
Basic Usage
Given:
{
"name": "Alice",
"age": 25
}
Put it in user.json.
Pretty-print it:
jq . user.json
Or:
cat user.json | jq .
jq . means:
Take the input JSON and output it unchanged, formatted nicely.
Extracting Values
Use .field:
jq '.name' user.json
Output:
"Alice"
jq '.age' user.json
Output:
25
Multiple levels:
{
"user": {
"name": "Alice"
}
}
jq '.user.name' data.json
Raw Strings
By default, jq outputs JSON strings with quotes:
jq '.name' user.json
"Alice"
Use -r for raw output:
jq -r '.name' user.json
Alice
This is especially useful in shell scripts.
Arrays
Given:
{
"users": [
{
"name": "Alice",
"age": 25
},
{
"name": "Bob",
"age": 30
}
]
}
Get the array:
jq '.users' users.json
Get the first item:
jq '.users[0]' users.json
Get the first user’s name:
jq '.users[0].name' users.json
Get all names:
jq '.users[].name' users.json
Output:
"Alice"
"Bob"
Array Indexing
.[0]
First element.
.[1]
Second element.
.[-1]
Last element.
Slices:
.[0:3]
First three elements.
Iterating with []
Given:
["apple", "banana", "orange"]
jq '.[]' fruits.json
Produces each element separately:
"apple"
"banana"
"orange"
This is one of the most important jq operations.
Filtering
Given:
[
{ "name": "Alice", "age": 25 },
{ "name": "Bob", "age": 17 },
{ "name": "Carol", "age": 30 }
]
Find users over 18:
jq '.[] | select(.age >= 18)' users.json
Get only their names:
jq '.[] | select(.age >= 18) | .name' users.json
Output:
"Alice"
"Carol"
The Pipe |
The pipe passes the result of one operation into another.
.users[] | .name
Read this as:
Get
.users, iterate over it, then get.namefrom each user.
Another example:
.users[] | select(.age >= 18) | .name
Read it as:
Get users → iterate → keep adults → get their names.
Creating Objects
You can construct new JSON objects:
jq '.[] | {name: .name, age: .age}' users.json
You can shorten repeated field names:
.[] | {name, age}
Renaming Fields
.[] | {
username: .name,
years_old: .age
}
Result:
{
"username": "Alice",
"years_old": 25
}
Arrays of Values
Get just the names as an array:
jq '[.[] | .name]' users.json
Result:
["Alice", "Bob", "Carol"]
The [...] collects the generated results into an array.
Length
length
For an array:
jq 'length' users.json
For a string:
.name | length
Sorting
Sort an array:
sort
Sort users by age:
sort_by(.age)
Descending:
sort_by(.age) | reverse
Selecting Fields
Given:
{
"name": "Alice",
"age": 25,
"email": "alice@example.com"
}
Select multiple fields:
{name, email}
Result:
{
"name": "Alice",
"email": "alice@example.com"
}
Default Values
Use //:
.username // "anonymous"
If .username is null or missing, "anonymous" is returned.
Example:
jq '.username // "anonymous"' user.json
Conditionals
if .age >= 18 then "adult" else "minor" end
Example:
jq '.[] | {
name,
status: (if .age >= 18 then "adult" else "minor" end)
}' users.json
String Interpolation
Use \(...):
"Hello, \(.name)!"
Example:
jq '.[] | "User: \(.name), Age: \(.age)"' users.json
Working with Command Output
A common use is processing JSON returned by another command:
some-command | jq '.name'
For example:
curl -s https://example.com/api/users | jq '.[].name'
jq is therefore very useful when working with APIs.
Useful Options
Pretty print
jq .
Raw strings
jq -r '.name'
Compact JSON
jq -c .
Read from a file
jq '.users' users.json
Read from stdin
cat users.json | jq '.users'
Common Patterns
Get all names
.[].name
Filter and get a field
.[] | select(.active == true) | .name
Count items
length
Count filtered items
[.[] | select(.active == true)] | length
Extract nested data
.users[].profile.email
Create a smaller object
.[] | {id, name}
Convert objects into strings
.[] | "\(.id): \(.name)"
The jq Mental Model
The most important thing to understand is:
JSON input
↓
jq filter
↓
JSON output
For example:
.users[]
means:
input
↓
.users
↓
each element
And:
.users[] | select(.age >= 18) | .name
means:
users
↓
each user
↓
keep adults
↓
get name
jq Cheat Sheet
| Task | Filter |
|---|---|
| Pretty print | . |
| Field | .name |
| Nested field | .user.name |
| Array element | .[0] |
| Iterate array | .[] |
| Filter | select(...) |
| Pipe | | |
| Length | length |
| Sort | sort |
| Sort by field | sort_by(.age) |
| Default value | .name // "Unknown" |
| Create object | {name, age} |
| Create array | [.[]] |
| Raw output | jq -r |
| Compact output | jq -c |
The Core 5 to Learn First
If you’re just starting, focus on these:
.field
[]
|
select(...)
{field1, field2}
Once these make sense, most everyday jq commands become much easier to read.