jq is a command-line processor for JSON: you pipe JSON in, apply a filter, and get
transformed JSON out. A jq program is a filter — a small expression that takes an
input value and produces zero or more output values. Filters compose with the pipe
| and the comma ,. This reference lists the operators, constructors, and the
built-in functions you use most.
Core concepts
jq processes a stream of JSON values. The filter you write runs once per input value and can produce zero, one, or many output values. Everything in jq is a filter, including field access and arithmetic — which is why they all compose with | the same way.
Navigation:
. # identity — return input unchanged
.field # field access
.["field"] # same, for keys with special chars
.[0] # array index
.[-1] # last element
.[2:5] # array slice
.[] # iterate: emit each element as a separate value
.. # recursive descent
Transformation:
map(f) # apply f to each array element, collect results
map(select(cond)) # filter array to matching elements
reduce .[] as $x (0; . + $x) # fold/reduce
Construction:
{name: .name, age: .age} # object construction
[.a, .b, .c] # array construction
[ .[] | select(.active) ] # collect filtered stream into array
Aggregation and introspection:
length # array/object length, string character count
keys # object keys as sorted array
values # object values as array
has("field") # boolean key presence test
to_entries # [{key:"k", value:v}, ...] — iterate object as pairs
from_entries # inverse of to_entries
add # sum array / concatenate strings / merge objects
unique # unique values in sorted array
group_by(.field) # partition array into sub-arrays by key
sort_by(.field) # sort array by key
How it works
jq reads a stream of JSON values and runs your filter against each one. The most
basic filter is . (identity), which returns the input untouched. From there you
navigate with .field, .[index] and the iterator .[], transform with map,
select, arithmetic and string functions, and assemble results with {} / []
constructors. The pipe | connects stages so each filter’s output becomes the next stage’s input.
Worked examples
Filter an array by condition and extract a field:
echo '{"users":[{"name":"A","age":30},{"name":"B","age":15}]}' \
| jq '.users | map(select(.age >= 18)) | map(.name)'
# => ["A"]
Iterate object keys:
echo '{"a":1,"b":2}' | jq 'to_entries | map(.key)'
# => ["a","b"]
Sum an array:
echo '[1,2,3]' | jq 'add'
# => 6
Reshape an object:
echo '{"first":"Jane","last":"Doe","age":32}' \
| jq '{fullName: (.first + " " + .last), age}'
# => {"fullName":"Jane Doe","age":32}
Command-line flags to know
| Flag | Effect |
|---|---|
-r | Raw output — strings without JSON quotes |
-c | Compact output — one JSON value per line |
-n | Null input — useful when building from scratch with input/inputs |
--arg name val | Bind a shell variable as a jq string variable $name |
--argjson name val | Bind a JSON-typed variable |
Wrap an iterating pipeline in [ ... ] to collect a stream back into an array. select emits nothing when its condition is false, so it naturally filters without needing an explicit removal step.