jq Command in Linux — JSON Processor with Examples
jq is a lightweight command-line JSON processor for Linux. It lets you slice, filter, map, and transform structured JSON data with a simple expression language — essential for working with modern APIs and configuration files.
What You’ll Learn
By the end of this tutorial, you’ll know how to access object keys, navigate arrays, select values by condition, pipe filters, map over arrays, get length, combine multiple filters, output raw strings, and pretty-print JSON.
Why jq Matters
JSON is everywhere — REST APIs, cloud configuration, Docker metadata, Kubernetes resources, and CI/CD pipelines. jq is the fastest way to extract, transform, and explore JSON from the command line. Durga Antivirus Pro uses jq to parse threat intelligence JSON feeds, and DodaZIP uses it to process API responses from cloud storage services.
jq Learning Path
flowchart LR
A[curl Command] --> B[jq Command<br/>You are here]
B --> C[API Testing & Automation]
B --> D[Shell Scripting]
style B fill:#f90,color:#fff
Syntax Overview
jq [options] 'filter' [file...]| Option | Description |
|---|---|
-r | Raw output (no quotes around strings) |
-c | Compact output (each JSON object on one line) |
-f file | Read filter from file |
--arg k v | Pass shell variable as jq variable |
10 Practical Examples
Create a sample JSON file:
cat > data.json << 'EOF'
{
"users": [
{
"id": 1,
"name": "Alice Johnson",
"email": "alice@example.com",
"role": "admin",
"active": true,
"salary": 75000,
"skills": ["Linux", "Python", "Docker"]
},
{
"id": 2,
"name": "Bob Smith",
"email": "bob@example.com",
"role": "user",
"active": false,
"salary": 62000,
"skills": ["JavaScript", "React"]
},
{
"id": 3,
"name": "Charlie Brown",
"email": "charlie@example.com",
"role": "user",
"active": true,
"salary": 88000,
"skills": ["Go", "Kubernetes", "AWS"]
}
],
"total": 3,
"source": "employees_db"
}
EOF1. Access Object Keys
Get the total count:
jq '.total' data.json3Get the source field:
jq '.source' data.json"employees_db"2. Array Access
Get the first user:
jq '.users[0]' data.json{
"id": 1,
"name": "Alice Johnson",
"email": "alice@example.com",
"role": "admin",
"active": true,
"salary": 75000,
"skills": ["Linux", "Python", "Docker"]
}Get all user names:
jq '.users[].name' data.json"Alice Johnson"
"Bob Smith"
"Charlie Brown"Get the last user’s skills:
jq '.users[-1].skills' data.json["Go", "Kubernetes", "AWS"]3. Select Values by Condition
Find active users:
jq '.users[] | select(.active == true)' data.json{
"id": 1,
"name": "Alice Johnson",
"active": true,
"salary": 75000
}
{
"id": 3,
"name": "Charlie Brown",
"active": true,
"salary": 88000
}Find users with salary > 70000:
jq '.users[] | select(.salary > 70000) | {name, salary}' data.json{
"name": "Alice Johnson",
"salary": 75000
}
{
"name": "Charlie Brown",
"salary": 88000
}4. Pipe (|) Filters
Get names of admins:
jq '.users[] | select(.role == "admin") | .name' data.json"Alice Johnson"Get name and email of inactive users:
jq '.users[] | select(.active == false) | {name, email}' data.json{
"name": "Bob Smith",
"email": "bob@example.com"
}5. Map Over Arrays
Transform all names to uppercase:
jq '[.users[] | {name: (.name | ascii_upcase), role}]' data.json[
{
"name": "ALICE JOHNSON",
"role": "admin"
},
{
"name": "BOB SMITH",
"role": "user"
},
{
"name": "CHARLIE BROWN",
"role": "user"
}
]Add a computed field:
jq '[.users[] | {name, annual_salary: (.salary * 12)}]' data.json[
{
"name": "Alice Johnson",
"annual_salary": 900000
},
{
"name": "Bob Smith",
"annual_salary": 744000
},
{
"name": "Charlie Brown",
"annual_salary": 1056000
}
]6. Length
Count users:
jq '.users | length' data.json3Count skills per user:
jq '.users[] | {name, skill_count: (.skills | length)}' data.json{
"name": "Alice Johnson",
"skill_count": 3
}
{
"name": "Bob Smith",
"skill_count": 2
}
{
"name": "Charlie Brown",
"skill_count": 3
}7. Multiple Filters
Get multiple fields:
jq '.users[] | .name, .email, .role' data.json"Alice Johnson"
"alice@example.com"
"admin"
"Bob Smith"
"bob@example.com"
"user"
"Charlie Brown"
"charlie@example.com"
"user"8. Raw Output (-r)
Without -r, strings are quoted:
jq '.users[0].email' data.json"alice@example.com"With -r, quotes are stripped:
jq -r '.users[0].email' data.jsonalice@example.comUseful for piping into other commands:
jq -r '.users[] | select(.role == "admin") | .email' data.json | while read email; do
echo "Emailing $email"
doneEmailing alice@example.com9. Filter by Condition with Multiple Criteria
Find users with salary > 60000 AND skill count >= 3:
jq '.users[] | select(.salary > 60000 and (.skills | length) >= 3)' data.json{
"id": 1,
"name": "Alice Johnson",
"salary": 75000,
"skills": ["Linux", "Python", "Docker"]
}
{
"id": 3,
"name": "Charlie Brown",
"salary": 88000,
"skills": ["Go", "Kubernetes", "AWS"]
}10. Pretty Print and Compact
Pretty print (default):
echo '{"name":"Alice","city":"NYC"}' | jq '.'{
"name": "Alice",
"city": "NYC"
}Compact output:
echo '{"name":"Alice","city":"NYC"}' | jq -c '.'{"name":"Alice","city":"NYC"}Common Use Cases
Pipe curl Output to jq
curl -s https://api.github.com/repos/curl/curl | jq '{stars: .stargazers_count, forks: .forks_count}'Extract Values from Nested JSON
jq -r '.users[] | "\(.name): \(.email)"' data.jsonAlice Johnson: alice@example.com
Bob Smith: bob@example.com
Charlie Brown: charlie@example.comCompute Averages
jq '[.users[].salary] | add / length' data.json75000Filter Array with Multiple Conditions
jq '[.users[] | select(.active and .salary > 70000)] | length' data.json2Common Mistakes
1. Forgetting the Filter
jq without a filter prints nothing. Always provide at least . to output the whole input.
2. Confusing Array and Object Access
Use .[] to iterate array elements. Use .key to access object keys. .[0] gets the first array element.
3. Not Using Raw Output for Text Processing
When piping jq to other commands, always use -r. Without it, strings remain quoted, which breaks downstream tools.
4. Missing Parentheses for Complex Expressions
select(.active and .salary > 70000) — the select function takes a single expression. Use parentheses for grouping with or/and.
Practice Questions
1. How do you get all values of a specific key across an array?
jq '.users[].name' data.json
2. What does jq -r '.users[0].email' output?
alice@example.com — no quotes around the string.
3. How do you count objects in an array?
jq '.users | length' data.json
4. How do you filter array elements by a condition?
jq '.users[] | select(.active == true)' data.json
5. Challenge: Write a jq filter that returns the average salary of active users only.
jq '[.users[] | select(.active) | .salary] | add / length' data.json
Mini Project: API Response Analyzer
#!/bin/bash
# api_analyze.sh — Analyze a JSON API response
# Usage: ./api_analyze.sh response.json
FILE="${1:-data.json}"
if [ ! -f "$FILE" ]; then
echo "Error: File not found: $FILE"
exit 1
fi
echo "=== JSON Analysis Report ==="
echo "File: $FILE"
echo ""
echo "Top-level keys:"
jq -r 'keys | .[]' "$FILE" | tr '\n' ' '
echo -e "\n"
echo "User summary:"
jq -r '["Name", "Role", "Active", "Salary"],
(.users[] | [.name, .role, .active, .salary]) |
@tsv' "$FILE" | column -t -s $'\t'
echo ""
echo "Stats:"
echo " Total users: $(jq '.users | length' "$FILE")"
echo " Active users: $(jq '[.users[] | select(.active)] | length' "$FILE")"
echo " Average salary: $(jq '[.users[].salary] | add / length' "$FILE")"Expected output:
=== JSON Analysis Report ===
File: data.json
Top-level keys:
source total users
User summary:
Name Role Active Salary
Alice Johnson admin true 75000
Bob Smith user false 62000
Charlie Brown user true 88000
Stats:
Total users: 3
Active users: 2
Average salary: 75000FAQ
What’s Next
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro