What I Was Trying to Do
I was hitting an API with curl and the JSON response came back as one giant unreadable line.
The server didn’t have Python installed, so python3 -m json.tool wasn’t an option — I had to figure out jq.
Environment
- Ubuntu 22.04
- jq 1.6
- bash 5.1
Installing jq
# Ubuntu / Debian
sudo apt install jq
# macOS
brew install jq
Verify installation:
jq --version
# jq-1.6
Basic Usage
To pretty-print a curl response, pipe it through jq '.':
curl -s https://api.example.com/users | jq '.'
To process a local file:
jq '.' response.json
Common Filters
Extract a specific key
# Extract "name" from {"name": "taro", "age": 30}
echo '{"name": "taro", "age": 30}' | jq '.name'
# "taro"
# Strip quotes with -r (raw output)
echo '{"name": "taro", "age": 30}' | jq -r '.name'
# taro
Working with arrays
# Expand all elements
echo '[{"id":1},{"id":2}]' | jq '.[]'
# Get the first element
echo '[{"id":1},{"id":2}]' | jq '.[0]'
# Extract a specific key from every element
echo '[{"name":"taro"},{"name":"hanako"}]' | jq '[.[].name]'
Nested keys
# {"user": {"profile": {"email": "test@example.com"}}}
echo '{"user":{"profile":{"email":"test@example.com"}}}' | jq '.user.profile.email'
# "test@example.com"
Filter with select
# Return only elements where age >= 30
echo '[{"name":"taro","age":30},{"name":"hanako","age":25}]' | jq '[.[] | select(.age >= 30)]'
Build a new object
echo '[{"name":"taro","age":30}]' | jq '.[] | {user: .name, years: .age}'
What I Tried First
I first tried grep to pull out specific fields, but it fell apart the moment the JSON was multi-line — values on the next line just didn’t match.
Then I attempted an awk approach, but awk really can’t handle nested JSON cleanly. I also tried a python3 -c "import json,sys;..." one-liner, but writing it from scratch every time was tedious enough that I finally just installed jq.
The Fix
Installing jq and piping curl output through it solved everything immediately.
curl -s https://api.example.com/users/1 | jq '.name'
I’ve been using it for all API debugging ever since. This fixed it.
Key Takeaways
.namereturns the value with surrounding double quotes. Use the-rflag when you need raw string output (e.g., assigning to a shell variable).[]expands every element of an array as separate outputs;.[0]returns only the first element — easy to mix these up early on- String comparisons inside
select()need== "value", not= "value". Spent a while wondering whyselect(.status = "active")threw an error - Always wrap jq filters in single quotes in shell scripts. Without them, bash interprets
$and|before jq ever sees them
Related Articles
- How to Use the curl Command
- How to Extract and Process Text with awk
- How to Search Files with grep and find in Linux
- How to Replace Strings with the sed Command
- Basic GitHub Actions Setup for Automated Deployment
Recommended Cloud Hosting
Looking for reliable cloud infrastructure? Check out these developer-friendly services.
- Cherry Servers - High-performance VPS and dedicated servers
- Cloudways - Managed cloud hosting for developers