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"]
FilterPasses through
numbers strings booleans nullsthat one type
arrays objectsthat one container
iterablesarrays and objects
scalarseverything that is not a container, null included
valueseverything 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
FilterOnReturns
lengthobject / array / string / number / nullkeys / elements / chars / abs / 0
utf8bytelengthstringencoded byte count
keysobject / arraysorted keys, or indices
keys_unsortedobjectkeys in insertion order
has(k)object / arraykey or index presence
emptyanythingnothing, 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.

FilterEmits
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.

FilterDirection
nowcurrent Unix seconds, a float
todate / todateiso8601seconds → "2023-11-14T22:13:20Z"
fromdate / fromdateiso8601that string → seconds
strftime(fmt)seconds or a broken-down array → string
strptime(fmt)string → broken-down array
gmtime / mktimeseconds ↔ broken-down UTC array
dateadd datesubnot 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
FilterDoes
errorraise the input as an error, exit 5
error("m")raise with a message
try f catch grun g with the error message as .
f?swallow the error, emit nothing
haltexit 0 immediately, skip remaining inputs
halt_errorprint the input to stderr raw, exit 5
halt_error(n)same with exit code n
input / inputspull the next / all remaining inputs, needs -n to start clean
$__loc__{"file":...,"line":...}, for debugging a def
debugpass through, print ["DEBUG:",.] to stderr
env / $ENVthe environment as an object