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}
| Form | Means |
|---|---|
{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:
| Filter | Outputs |
|---|---|
.items[].id | 1 2 3, three values |
[.items[].id] | [1,2,3], one value |
.items | the 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
| Function | Emits |
|---|---|
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
| Operator | Behavior |
|---|---|
a + b | shallow merge, right side wins per key |
a * b | deep 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.
| Expression | Result |
|---|---|
1 + 2 | 3 |
"a" + "b" | "ab" |
[1] + [2] | [1,2] |
{a:1} + {b:2} | {"a":1,"b":2} |
null + 1 | 1, null is the identity for + |
["a","b"] - ["a"] | ["b"], set difference on arrays |
"ab" * 3 | "ababab" |
"a,b" / "," | ["a","b"], same as split(",") |
10 / 3 | 3.3333333333333335, floats always |
10 % 3 | 1, 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.