jq Filter Examples: Command-Line JSON Query Cheat Sheet

jq is a command-line JSON processor that lets you slice, filter, map, and transform JSON using a compact filter language. The identity filter . is the simplest filter; more complex expressions let you select fields, filter arrays, reshape JSON, and compute new values — all without writing a script.

Install jq

# macOS
brew install jq

# Ubuntu / Debian
sudo apt-get install jq

# Windows (Chocolatey)
choco install jq

# Or download binaries from https://jqlang.org/download/

Verify the install with jq --version. jq has no runtime dependencies — the binary is self-contained.

Basic field selection

The dot . is the identity filter. Append a field name to select a value from an object. Chain dots to traverse nested fields. Use {field1, field2} to pick multiple fields into a new object.

# Identity: output unchanged (and pretty-print)
echo '{"name":"Alice","age":30}' | jq '.'

# Select a single field
echo '{"name":"Alice","age":30}' | jq '.name'
# "Alice"

# Nested field access
echo '{"user":{"name":"Alice","city":"Paris"}}' | jq '.user.city'
# "Paris"

# Pick multiple fields into a new object
echo '{"name":"Alice","age":30,"city":"Paris"}' | jq '{name, age}'
# {"name":"Alice","age":30}

# Rename a field in the output
echo '{"user_id":1,"full_name":"Alice"}' | jq '{id: .user_id, name: .full_name}'
# {"id":1,"name":"Alice"}

Array operations

Use .[] to iterate every element of an array. Use .[n] to access by index. Use .[start:end] to slice. Wrap .[] in [...] to collect output back into an array.

# Iterate all elements (outputs each on a separate line)
echo '[1,2,3]' | jq '.[]'

# Get element by index (zero-based)
echo '["a","b","c"]' | jq '.[1]'
# "b"

# Slice (inclusive start, exclusive end)
echo '[1,2,3,4,5]' | jq '.[2:4]'
# [3,4]

# Array length
echo '[1,2,3]' | jq 'length'
# 3

# Get a field from each object in an array
echo '[{"name":"Alice"},{"name":"Bob"}]' | jq '.[].name'
# "Alice"
# "Bob"

# Collect field values into a new array
echo '[{"name":"Alice"},{"name":"Bob"}]' | jq '[.[].name]'
# ["Alice","Bob"]

Pipe and select (filtering)

The pipe | chains filters left to right — the output of the left filter becomes the input of the right. select(condition) passes through only elements that match. Use test() for regex matching and not to negate.

# Filter objects where age > 27
echo '{"users":[{"name":"Alice","age":30},{"name":"Bob","age":25}]}' |   jq '.users[] | select(.age > 27)'
# {"name":"Alice","age":30}

# Filter by exact string match
echo '[{"status":"active"},{"status":"inactive"}]' |   jq '.[] | select(.status == "active")'

# Filter by regex — test() returns true/false
echo '[{"email":"a@gmail.com"},{"email":"b@corp.com"}]' |   jq '.[] | select(.email | test("@gmail\.com"))'

# Negate a condition
echo '[{"active":true},{"active":false}]' |   jq '.[] | select(.active | not)'

# Collect filtered results into an array
echo '[{"age":20},{"age":35},{"age":28}]' |   jq '[.[] | select(.age > 25)]'

Transform and reshape

Build new objects by combining fields, interpolate strings with "\(.field)", and use map() as shorthand for [.[] | ...] to transform every element in an array.

# Rename fields and build a new object
echo '[{"user_id":1,"full_name":"Alice"}]' |   jq '.[] | {id: .user_id, label: .full_name}'

# Add a computed field using string interpolation
echo '[{"first":"Alice","last":"Smith"}]' |   jq '.[] | . + {full_name: "\(.first) \(.last)"}'
# {"first":"Alice","last":"Smith","full_name":"Alice Smith"}

# map() — transform every element, return an array
echo '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]' |   jq 'map({id, name})'

# map() with select() — filter and transform in one step
echo '[{"active":true,"name":"Alice"},{"active":false,"name":"Bob"}]' |   jq 'map(select(.active)) | map(.name)'
# ["Alice"]

# Compute new values
echo '[{"price":10},{"price":20}]' |   jq 'map(.price * 1.1)'
# [11,22]

Useful built-in functions

jq includes a rich standard library. Here are the functions used most often in real-world data processing:

# keys — sorted list of object keys
echo '{"b":2,"a":1}' | jq 'keys'
# ["a","b"]

# values — list of object values (in key order)
echo '{"name":"Alice","id":42}' | jq 'values'

# has() — check if a key exists
echo '{"name":"Alice"}' | jq 'has("email")'
# false

# to_entries — convert object to [{key, value}] pairs
echo '{"a":1,"b":2}' | jq 'to_entries'
# [{"key":"a","value":1},{"key":"b","value":2}]

# from_entries — convert [{key, value}] back to an object
echo '[{"key":"a","value":1}]' | jq 'from_entries'
# {"a":1}

# group_by — group array elements by a field
echo '[{"dept":"eng","name":"Alice"},{"dept":"hr","name":"Bob"},{"dept":"eng","name":"Carol"}]' |   jq 'group_by(.dept)'

# unique_by — deduplicate by a field
echo '[{"id":1,"name":"Alice"},{"id":1,"name":"Alice2"}]' |   jq 'unique_by(.id)'

# sort_by — sort ascending by a field
echo '[{"name":"Carol"},{"name":"Alice"},{"name":"Bob"}]' |   jq 'sort_by(.name)'

# sort descending
echo '[{"price":30},{"price":10},{"price":20}]' |   jq 'sort_by(.price) | reverse'

# reduce — fold an array into a single value
echo '[{"price":10},{"price":20},{"price":15}]' |   jq 'reduce .[] as $item (0; . + $item.price)'
# 45

Output options

Control how jq formats its output and what it reads using flags. The most commonly needed flags are -r (raw strings), -c (compact), and -s (slurp multiple files into one array).

# -r: raw string output — no surrounding quotes
jq -r '.name' data.json
# Alice  (not "Alice")

# -c: compact output — no whitespace
jq -c '.' data.json

# Read from a file directly
jq '.' data.json

# Run the same filter across multiple files
jq '.name' file1.json file2.json

# -n: null input — generate JSON without reading stdin
jq -n '{"timestamp": now | todate}'

# -s: slurp — read all inputs into a single array, then filter
jq -s '.' *.json

# -e: exit with non-zero status if output is false or null (useful in scripts)
jq -e '.active' config.json && echo "active" || echo "inactive"

# Combine flags: raw output + compact from a file
jq -rc '.[].name' users.json

Try JSONPath in your browser

jq is a CLI-only tool. For browser-based JSON querying, try Jsonic's JSONPath Tester. JSONPath uses a simpler path syntax ($.users[*].name) suited for extraction; jq's filter pipeline is more powerful for transformation. Both are worth knowing.

Open JSONPath Tester

Frequently asked questions

What is jq and what is it used for?

jq is a lightweight, portable command-line JSON processor written in C with no runtime dependencies. It applies a filter expression to JSON input and produces JSON (or text) output. Common uses: extract fields from API responses (curl ... | jq '.data[].name'), filter log entries by field values, transform JSON shape for downstream tools, validate structure, count records, and pipe results into shell scripts. jq is available on Linux, macOS, and Windows.

What does the dot (.) mean in jq?

The dot . is the identity filter — it outputs the input unchanged. .field selects a field from an object. .field.nested chains field accesses. .[0] selects an array element by index. .[] iterates all array elements or all object values. These compose: .users[].name means "from the users array, get the name field of each element."

How do I filter a JSON array in jq?

Use select() combined with pipe: .[] | select(.age > 30). The .[] iterates each element;select() passes through only elements where the condition is true. To collect filtered elements back into an array, wrap in [...]: [.[] | select(.active == true)]. The map(select(...)) shorthand does the same thing more readably.

What is the difference between .[] and map() in jq?

.[] outputs each element as a separate JSON value on stdout. map(f) is equivalent to [.[] | f] — it applies filter f to each element and collects the results into an array. Use .[] when you want to pipe elements to further filters. Use map() when you want to transform each element and get an array back.

How do I extract raw string values (without quotes) from jq?

Use the -r flag: jq -r '.name' outputs Alice instead of "Alice". This is essential when piping jq output to shell commands: for user in $(jq -r '.[].name' users.json); do echo "$user"; done. Without -r, you get JSON strings with surrounding quotes, which shell commands treat as literal characters including the quotes.

What is the difference between jq and JSONPath?

Both query JSON, but they work differently. JSONPath uses a path expression syntax ($.users[*].name) focused on selection. jq uses a filter pipeline that can select, transform, compute, and reshape JSON in one expression. jq is more powerful for data transformation; JSONPath is simpler for extraction. JSONPath is built into some databases and APIs; jq is a CLI tool. For a browser-based JSONPath tester, see Jsonic's JSONPath Tester.