On this page

Every API you talk to returns JSON. Every config file is JSON. Every log pipeline emits JSON. And yet most people still pipe curl output through grep and pray.

jq is the tool that makes JSON usable from the command line. Once you learn the basics, you will never go back.

Basics#

Pretty-print some JSON:

bash
curl -s https://api.github.com/users/torvalds | jq .

Extract a single field:

bash
echo '{"name": "Linus", "repos": 5}' | jq .name
# "Linus"

Drop the quotes with -r:

bash
echo '{"name": "Linus"}' | jq -r .name
# Linus

Arrays#

Get the first element:

bash
echo '[1, 2, 3]' | jq '.[0]'
# 1

Iterate over all elements:

bash
echo '[{"name": "a"}, {"name": "b"}]' | jq '.[].name'
# "a"
# "b"

Filtering#

This is where it gets powerful. Say you have a list of GitHub repos:

bash
curl -s https://api.github.com/users/torvalds/repos | \
  jq '[.[] | select(.stargazers_count > 1000)] | length'

That filters repos with more than 1000 stars and counts them.

Constructing Objects#

You can reshape JSON on the fly:

bash
curl -s https://api.github.com/users/torvalds/repos | \
  jq '.[] | {name: .name, stars: .stargazers_count, lang: .language}'

This outputs a new object for each repo with only the fields you care about.

Real World: Parsing Docker#

List container names and their memory usage:

bash
docker stats --no-stream --format '{{json .}}' | \
  jq -r '[.Name, .MemUsage] | @tsv'

Find containers using more than 100MB:

bash
docker stats --no-stream --format '{{json .}}' | \
  jq -r 'select(.MemPerc | gsub("%"; "") | tonumber > 1) | .Name'

Working With Nested Data#

Given deeply nested JSON:

json
{
  "data": {
    "users": [
      {"id": 1, "profile": {"email": "[email protected]"}},
      {"id": 2, "profile": {"email": "[email protected]"}}
    ]
  }
}

Extract all emails:

bash
jq '[.data.users[].profile.email]' data.json
# ["[email protected]", "[email protected]"]

Combining With Other Tools#

jq plays well with the rest of the Unix toolkit:

bash
# Get all unique languages across repos
curl -s https://api.github.com/users/torvalds/repos | \
  jq -r '.[].language // empty' | sort -u

# Convert JSON array to lines for xargs
echo '["file1.txt", "file2.txt"]' | jq -r '.[]' | xargs rm

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

The Cheat Sheet#

PatternWhat it does
.fieldGet field
.[]Iterate array
select(cond)Filter
map(expr)Transform array
lengthCount
keysObject keys
to_entriesObject to key-value pairs
@csvOutput as CSV
@tsvOutput as TSV
//Default value

jq has a learning curve, but it is one of those tools where the investment pays off within a week. Every time you find yourself writing a Python script just to parse some JSON, remember that jq probably does it in one line.