{ }jsonkitOpen

jq cheat sheet: filters, select, map and examples

9 min read · updated 2026-10-01

This jq cheat sheet lists the filters you use most, each run against one sample file with its real output. jq is a command-line JSON processor: you give it a filter and it reads JSON, transforms it and prints the result.

Every example was run with jq 1.8. Paste the sample and any filter into the jq tester to try them in your browser.

The sample file

All examples use this file, users.json:

users.jsonjson
{
  "users": [
    { "id": 1, "name": "Ada", "email": "ada@example.com", "role": "admin", "active": true, "tags": ["math", "engines"] },
    { "id": 2, "name": "Grace", "email": "grace@example.com", "role": "editor", "active": false, "tags": ["cobol"] },
    { "id": 3, "name": "Linus", "email": "linus@example.com", "role": "editor", "active": true, "tags": [] }
  ]
}

On the command line the pattern is jq 'FILTER' users.json. Quote the filter with single quotes so the shell leaves it alone.

Basic paths

FilterResult
.The whole document, pretty-printed
.users[0].name"Ada"
.users[-1].email"linus@example.com"
.users[].name"Ada", "Grace", "Linus" as three separate outputs
.users[1:]The last two users
.users | length3
.users[0] | keys["active","email","id","name","role","tags"] (sorted)
.users[0].missingnull, not an error
.users[0].nickname // "none""none", the alternative operator fills in a default

.[] iterates: it outputs each element of an array (or each value of an object) as its own result. The pipe | sends every result into the next filter, like a shell pipe.

Filter with select

select(condition) keeps a value when the condition is true and drops it otherwise.

FilterResult
.users[] | select(.active) | .name"Ada", "Linus"
.users[] | select(.role == "editor" and .active) | .name"Linus"
.users[] | select(.id == 2) | .email"grace@example.com"
.users[] | select(.email | test("^g")) | .name"Grace" (regular expression)
.users[] | select(.tags | index("cobol")) | .name"Grace"
.users | map(select(.tags | length > 0)) | length2
.users | any(.role == "admin")true
.users | all(.active)false

Reshape with map and object construction

FilterResult
.users | map(.email)["ada@example.com","grace@example.com","linus@example.com"]
.users | map({name, role})[{"name":"Ada","role":"admin"}, ...]
{count: (.users | length), names: [.users[].name]}{"count":3,"names":["Ada","Grace","Linus"]}
.users[] | {name, upper: (.name | ascii_upcase)}{"name":"Ada","upper":"ADA"} and so on
[.users[].tags[]]["math","engines","cobol"]
del(.users[].email)The document without any email fields
.users[0] | with_entries(select(.key != "tags"))Ada's object without tags
.users | map({(.name): .id}) | add{"Ada":1,"Grace":2,"Linus":3}

{name} is short for {name: .name}. Parentheses around a key, as in {(.name): .id}, use a computed value as the key.

Sort, group and aggregate

FilterResult
.users | sort_by(.name) | map(.name)["Ada","Grace","Linus"]
.users | map(.name) | sort | reverse["Linus","Grace","Ada"]
.users | map(.role) | unique["admin","editor"]
.users | group_by(.role) | map({role: .[0].role, count: length})[{"role":"admin","count":1},{"role":"editor","count":2}]
.users | map(.id) | add6
.users | max_by(.id) | .name"Linus"
reduce .users[] as $u (0; . + $u.id)6, the same sum with reduce

Strings and output formats

FilterResult
.users[] | "\(.name) <\(.email)>"Ada <ada@example.com> and so on (string interpolation)
.users[] | .tags | join(", ")"math, engines", "cobol", ""
.users[] | [.id, .name, .role] | @csv1,"Ada","admin" (with -r)
.users[] | [.id, .name] | @tsvTab-separated rows (with -r)
.users[0].name | @base64"QWRh"
.users | map(.id) | @json"[1,2,3]", JSON as a string
"42" | tonumber42

@csv and @tsv need an array as input. Use them with the -r flag so the rows print as plain text instead of quoted JSON strings.

Update values

FilterResult
.users[0].name |= ascii_upcaseAda's name becomes "ADA"
.users[] |= (.active = true)Every user becomes active
(.users[] | select(.id == 2) | .role) = "admin"Grace's role becomes "admin"
if .users[0].active then "yes" else "no" end"yes"

= sets a value. |= updates a value with a filter that receives the old value. Both return the whole document with the change applied.

Command-line flags

FlagWhat it does
-rRaw output: print strings without quotes
-cCompact output: one result per line
-sSlurp: read every input value into one array first
-SSort the keys of every object in the output
-nNull input: start with null and read input with input or inputs
-eSet the exit status from the last output, useful in scripts
--arg name valuePass a string, used as $name in the filter
--argjson name valuePass a JSON value, such as a number
Flags in practicebash
# Emails of active users, one per line
jq -r '.users[] | select(.active) | .email' users.json

# Pass a value from the shell
jq --arg role editor '.users[] | select(.role == $role) | .name' users.json

# Count objects in a JSON Lines file
jq -s 'length' events.jsonl

The jq tester has toggles for -r, -c, -s and -S.

jq vs JSONPath

JSONPath only selects values. jq selects, filters, reshapes and computes, so anything that changes the output shape, such as counting, renaming or grouping, needs jq. The JSONPath cheat sheet has a side-by-side table of the same queries in both languages.

jqjq TesterRun any filter from this page against your own JSON.→

Frequently asked questions

What does .[] mean in jq?

It iterates over an array or object and outputs each element as a separate result. .users[] outputs every user, and .users[].name outputs every name.

How do I filter an array in jq?

Use select inside an iteration: .users[] | select(.active). To keep the result as one array, write [.users[] | select(.active)] or .users | map(select(.active)).

How do I get raw strings without quotes from jq?

Add the -r flag. jq -r '.users[].name' prints Ada, Grace and Linus as plain text, one per line.

How do I count items with jq?

Pipe an array into length, as in .users | length. To count values from a stream, wrap it first: [.users[] | select(.active)] | length.

Can I run jq online?

Yes. The JsonKit jq tester runs jq 1.8 compiled to WebAssembly in your browser, with toggles for the -r, -c, -s and -S flags.