jq Cheatsheet
Built-in Functions
Use this jq reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Type inspection
type returns one of six strings. The type filters are shorter and are what you
actually want next to .. and .[], because each passes matching values through
and drops everything else.
jq -cn '[1,"a",null,true,[],{}] | [.[] | type]' # ["number","string","null","boolean","array","object"]
| Filter | Passes through |
|---|---|
numbers strings booleans nulls | that one type |
arrays objects | that one container |
iterables | arrays and objects |
scalars | everything that is not a container, null included |
values | everything except null |
jq -c '[.. | numbers]' data.json # [1,10,2,20,3,30,3] jq -cn '[[1,null] | .[] | values]' # [1] jq -cn '[[1,null] | .[] | nulls]' # [null] jq -c '[.. | objects | keys] | length' data.json
length and friends
jq -c 'length' data.json # 5, object key count jq -c '.items | length' # 3, array element count jq -c '.name | length' # 3, string CHARACTER count jq -cn 'null | length' # 0 jq -cn '-5 | length' # 5, absolute value jq -cn '"é" | length, utf8bytelength' # 1 then 2
| Filter | On | Returns |
|---|---|---|
length | object / array / string / number / null | keys / elements / chars / abs / 0 |
utf8bytelength | string | encoded byte count |
keys | object / array | sorted keys, or indices |
keys_unsorted | object | keys in insertion order |
has(k) | object / array | key or index presence |
empty | anything | nothing, zero outputs |
Arrays and aggregation
jq -c '[.items[].price] | add' data.json # 60 jq -c '[.items[].price] | add / length' # 20, the mean jq -cn '[1,2,3] | min, max, add, length' # 1 3 6 3 jq -cn '[] | add' # null, NOT 0 jq -cn '[] | add // 0' # 0 jq -cn '["a","b"] | add' # "ab", add concatenates jq -cn '[{a:1},{b:2}] | add' # {"a":1,"b":2}, add merges jq -cn '[3,1,2] | sort, (sort | reverse), unique' jq -cn '[[1,[2,[3]]]] | flatten, flatten(1)' jq -cn '[1,2,3] | any(. > 2), all(. > 0)' # true true jq -cn '[1,2,3,1,2] | indices([1,2])' # [0,3], subsequence starts jq -cn '"abcabc" | indices("b"), index("b"), rindex("b")' # [1,4] 1 4
add is reduce .[] as $x (null; . + $x), which is why it merges objects,
concatenates strings, and returns null rather than 0 on an empty array.
Generators
A generator is any filter with more than one output. These are the built-in ones,
and they are the closest jq has to a for loop.
| Filter | Emits |
|---|---|
range(n) | 0 up to n-1 |
range(from; to) | from up to to-1 |
range(from; to; step) | stepped, negative steps allowed |
limit(n; f) | at most the first n outputs of f |
first(f) / last(f) | one output, first short-circuits |
nth(n; f) | the zero-indexed nth output of f |
until(cond; f) | applies f until cond, emits one value |
while(cond; f) | emits every value while cond holds |
recurse(f) | the input, then f, then f|f, until f is empty |
isempty(f) | true when f has no outputs |
jq -cn '[range(3)], [range(1;4)], [range(0;10;3)]' # [0,1,2] [1,2,3] [0,3,6,9] jq -cn '[limit(2; range(1000))]' # [0,1], range is lazy jq -cn 'first(range(5)), last(range(5)), nth(2; range(5))' # 0 4 2 jq -cn '1 | until(. > 100; . * 2)' # 128, one output jq -cn '1 | [while(. < 100; . * 2)]' # [1,2,4,8,16,32,64] jq -cn '1 | [limit(5; recurse(. * 2))]' # [1,2,4,8,16] jq -c 'isempty(.items[] | select(.price > 99))' data.json # true
limit is the reason a recurse or range that never terminates is still safe.
jq streams, so limit(2; range(1e9)) never builds the full sequence.
Numbers, strings, and conversion
jq -cn '3.7 | floor, ceil, round, (. | fabs)' # 3 4 4 3.7 jq -cn '[2|sqrt], [pow(2;10)], [8|log2], [1|exp]' jq -cn 'infinite, (nan|isnan), (infinite|isinfinite)' jq -cn '1 | tostring' # "1" jq -cn '"2" | tonumber' # 2 jq -cn '"x" | tonumber' # error, exit 5 jq -cn '{a:1} | tojson' # "{\"a\":1}", a JSON STRING jq -cn '"{\"a\":1}" | fromjson'# {"a":1} jq -rn '[1,2] | tostring' # [1,2], tostring on a container is tojson
tostring on a container is the same as tojson. tojson on a string adds the
quotes and escapes, tostring on a string is a no-op. That difference is what makes
@json and @text behave differently in an interpolation.
Dates
jq speaks Unix seconds and ISO 8601 with a Z. Anything with an offset needs
strptime and a format string.
| Filter | Direction |
|---|---|
now | current Unix seconds, a float |
todate / todateiso8601 | seconds → "2023-11-14T22:13:20Z" |
fromdate / fromdateiso8601 | that string → seconds |
strftime(fmt) | seconds or a broken-down array → string |
strptime(fmt) | string → broken-down array |
gmtime / mktime | seconds ↔ broken-down UTC array |
dateadd datesub | not present, do the arithmetic on seconds |
jq -rn '1700000000 | todate' # 2023-11-14T22:13:20Z jq -rn '"2023-11-14T22:13:20Z" | fromdate' # 1700000000 jq -rn '1700000000 | strftime("%Y-%m-%d")' # 2023-11-14 jq -rn '"2023-11-14" | strptime("%Y-%m-%d") | mktime' # 1699920000 jq -cn '1700000000 | gmtime' # [2023,10,14,22,13,20,2,317], month is 0-based jq -rn 'now | todate' jq -r '.items[] | (now - 86400 | todate) as $d | "\(.id) \($d)"' data.json
gmtime months are 0-based and the last two fields are weekday and day of year.
fromdate rejects anything that is not exactly ISO 8601 with a Z.
Errors, exit, and reading more input
jq -cn 'try error("boom") catch .' # "boom" jq -n 'error("x")' # writes to stderr, exit 5 jq -rn '"msg\n" | halt_error' # stderr as-is, no newline added, exit 5 jq -rn '"msg\n" | halt_error(3)' # same, exit 3 jq -n 'halt' # stop now, exit 0 jq -cn '[inputs]' multi.json # every remaining input as an array jq -c 'input' multi.json # the NEXT input, not the first jq -r 'input_filename' data.json # "data.json", null on stdin jq -c '[., input_line_number]' # the line each value ended on
| Filter | Does |
|---|---|
error | raise the input as an error, exit 5 |
error("m") | raise with a message |
try f catch g | run g with the error message as . |
f? | swallow the error, emit nothing |
halt | exit 0 immediately, skip remaining inputs |
halt_error | print the input to stderr raw, exit 5 |
halt_error(n) | same with exit code n |
input / inputs | pull the next / all remaining inputs, needs -n to start clean |
$__loc__ | {"file":...,"line":...}, for debugging a def |
debug | pass through, print ["DEBUG:",.] to stderr |
env / $ENV | the environment as an object |