jq Cheatsheet

Object and Array Construction

Use this jq reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Object construction

{} builds a new object. Values are filters, evaluated against the current input.

jq -c '{n: .name, v: .version}'          # {"n":"api","v":"2.1.0"}
jq -c '{a: (.items | length), b: [.items[].id]}'   # {"a":3,"b":[1,2,3]}
jq -c '.items[0] | {id, price}'          # {"id":1,"price":10}
FormMeans
{k: f}key k, value from filter f
{k}shorthand for {k: .k}
{"a b": 1}quoted literal key
{(f): v}computed key, f must produce a string
{$var}shorthand for {var: $var}
{"x": .a.b}any path expression as the value
jq -c '{(.name): .meta.count}'           # {"api":3}
jq -c --arg k dyn '{($k): 1}'            # {"dyn":1}
jq -c --arg env prod '{$env, name}'      # {"env":"prod","name":"api"}

The parentheses around a computed key are required. {.name: 1} is a syntax error.

Shorthand is the workhorse

{name, version} is the fastest way to project a subset of fields, and it is the most common thing in real jq programs.

# keep four fields out of a big API object
jq -c '.items[] | {id, name, price, cat}'

# rename while projecting, mix both forms
jq -c '.items[] | {id, label: .name, cost: .price}'

Shorthand only works for keys that are bare identifiers. {my-key} does not parse, write {"my-key": .["my-key"]}.

Array construction

[...] runs the filter inside and collects every output into one array. It is how a stream becomes a single value.

jq -c '[.name, .version]'      # ["api","2.1.0"]
jq -c '[.items[].price]'       # [10,20,30]
jq -c '[.items[] | select(.cat == "x") | .id]'   # [1,3]
jq -c '[]'                     # [], the empty array

Compare, with and without the brackets:

FilterOutputs
.items[].id1 2 3, three values
[.items[].id][1,2,3], one value
.itemsthe array as it already is
[.items][[…]], wrapped one level deeper

Multiple outputs multiply

A construction whose value filter emits several outputs produces several objects, one per combination. This surprises everyone once.

jq -c '{id: .items[].id}'
# {"id":1}
# {"id":2}
# {"id":3}
jq -c '[{id: .items[].id}]'
# [{"id":1},{"id":2},{"id":3}]

Two multi-output values give the Cartesian product, so {a: (1,2), b: (3,4)} emits four objects. Wrap the inner filter in [...] when you wanted one object with an array inside.

range and limit

jq -c '[range(3)]'            # [0,1,2]
jq -c '[range(2; 5)]'         # [2,3,4]
jq -c '[range(0; 10; 3)]'     # [0,3,6,9]
jq -c '[range(5; 0; -1)]'     # [5,4,3,2,1]
jq -c '[limit(2; .items[].id)]'   # [1,2], stops early
FunctionEmits
range(n)0 to n-1
range(from; upto)from to upto-1
range(from; upto; by)stepped, by may be negative
limit(n; f)the first n outputs of f
first(f) / last(f)one output
nth(n; f)the nth output, zero-based
repeat(f)infinite, needs limit or until

limit is lazy, so limit(1; .[] | select(.big)) stops at the first hit instead of scanning the whole array.

Merging objects

OperatorBehavior
a + bshallow merge, right side wins per key
a * bdeep recursive merge, right side wins at the leaves
jq -c '.meta + {extra: 1}'                    # {"count":3,"extra":1}
jq -cn '{a:{b:1,c:2}} + {a:{b:9}}'            # {"a":{"b":9}}, c is gone
jq -cn '{a:{b:1,c:2}} * {a:{b:9}}'            # {"a":{"b":9,"c":2}}

Use * for config-style overrides, where you want the base object's other keys to survive. Use + when the right side is meant to replace whole subtrees.

Arithmetic across types

+ is overloaded, and each pairing is worth knowing.

ExpressionResult
1 + 23
"a" + "b""ab"
[1] + [2][1,2]
{a:1} + {b:2}{"a":1,"b":2}
null + 11, null is the identity for +
["a","b"] - ["a"]["b"], set difference on arrays
"ab" * 3"ababab"
"a,b" / ","["a","b"], same as split(",")
10 / 33.3333333333333335, floats always
10 % 31, integer remainder

null + x returning x is what makes add work on an array containing nulls. Adding a string to a number is an error, so tostring or tonumber first.