env.dev

jq Cheat Sheet — Filter, Transform & Query JSON from the Command Line

Quick reference for jq: basic filters, pipes, selectors, string operations, array and object manipulation, reduce, path expressions, output formatting, and passing variables.

Last updated:

jq is a lightweight command-line JSON processor for slicing, filtering, mapping, and transforming structured data. This cheat sheet covers the most essential jq filters, operators, and built-in functions organized by workflow — from basic field access to advanced aggregation and formatting.

Basic Filters

FilterDescription
.Identity — pretty-print the entire input
.fooAccess object key "foo"
.foo.barAccess nested key "bar" inside "foo"
.foo?Access key "foo", suppressing errors if missing
."hyphenated-key"Access keys that contain special characters
.[]Iterate over all elements of an array or object
.[0]Access first element of an array
.[-1]Access last element of an array
.[2:5]Slice array from index 2 to 4 (exclusive end)

How Do You Pipe and Combine Filters?

ExpressionDescription
.foo | .barPipe — feed output of left filter into right filter
.foo, .barComma — output both values (multiple outputs)
.[] | .nameIterate array and extract "name" from each element
[.[] | .name]Wrap iterated results back into an array
{name: .foo, id: .bar}Construct a new object from selected fields
[.[] | {name, age}]Project specific fields from an array of objects

Comparison and Logic Operators

OperatorDescription
==, !=Equality and inequality
<, <=, >, >=Numeric/string comparison
and, or, notBoolean logic operators
if .x then .y else .z endConditional expression
// "default"Alternative operator — use right value if left is null or false
.x // emptySuppress null values (emit nothing instead)

How Do You Filter and Select Elements?

ExpressionDescription
select(.age > 30)Keep elements where condition is true
select(.name == "Alice")Keep elements matching exact value
select(.tags | contains(["go"]))Keep elements whose tags array includes "go"
map(select(.active))Filter an array to only active items
limit(3; .[])Take only the first 3 outputs
first(.[])Take the first output only
last(.[])Take the last output only
.[] | select(.price) | .priceExtract field only from objects that have it

String Operations

ExpressionDescription
"Hello, \(.name)!"String interpolation using \( )
ascii_downcaseConvert to lowercase
ascii_upcaseConvert to uppercase
split("-")Split string into array on delimiter
join(", ")Join array into string with delimiter
test("^foo")Test if string matches regex (returns boolean)
match("([0-9]+)")Return regex match object with offset/length
capture("(?<y>[0-9]{4})")Named capture groups returned as object
gsub("old"; "new")Replace all occurrences of a regex
sub("old"; "new")Replace first occurrence of a regex
ltrimstr("prefix")Remove prefix from string
rtrimstr("suffix")Remove suffix from string
lengthString length (also works on arrays/objects)
startswith("http")Check if string starts with value
endswith(".json")Check if string ends with value

Array Operations

ExpressionDescription
map(.price * 2)Apply expression to every element
map_values(. + 1)Apply expression to every value in an object
sortSort array (numbers/strings)
sort_by(.name)Sort array of objects by a key
reverseReverse an array
uniqueRemove duplicates
unique_by(.id)Remove duplicates by a key
flattenFlatten nested arrays one level
flatten(2)Flatten up to 2 levels deep
group_by(.type)Group array of objects by key (returns nested arrays)
min_by(.price)Object with minimum value for key
max_by(.price)Object with maximum value for key
addSum an array of numbers, or concatenate strings/arrays
any(. > 5)True if any element satisfies condition
all(. > 0)True if all elements satisfy condition
indices("foo")All indices where value appears
[., .[]] | lengthLength of the array

Object Operations

ExpressionDescription
keysGet array of object keys (sorted)
keys_unsortedGet array of object keys (original order)
valuesGet array of object values
has("name")Check if object has key (returns boolean)
in({"a":1})Check if input key exists in given object
to_entriesConvert {k:v} to [{key:k, value:v}, ...]
from_entriesConvert [{key:k, value:v}] back to {k:v}
with_entries(select(.value > 0))Filter object key-value pairs
with_entries(.key |= "prefix_" + .)Transform all keys
. + {newkey: "val"}Add or overwrite a key in an object
del(.unwanted)Remove a key from an object
. * {a: {b: 2}}Recursive merge (deep merge)

Reduce and Aggregation

ExpressionDescription
[.[] | .price] | addSum a specific field across array of objects
lengthCount elements in array or keys in object
[.[] | .score] | add / lengthCalculate average of a field
reduce .[] as $x (0; . + $x)Custom reduction — sum example
reduce .[] as $x ({}; . + {($x.k): $x.v})Build object from array using reduce
group_by(.type) | map({type: .[0].type, count: length})Count items per group
[.[] | .amount] | [min, max]Get min and max of a field

Type Functions and Conversions

ExpressionDescription
typeReturn type as string: "object", "array", "string", "number", "boolean", "null"
tostringConvert value to string
tonumberConvert string to number
arrays, objects, strings, numbers, booleans, nullsSelect only values of that type
notBoolean negation
emptyProduce no output (useful in conditionals)
nullLiteral null value
error("msg")Abort with error message
try .foo catch "fallback"Try expression, use fallback on error
try .fooSilently suppress errors (same as .foo?)

Output Formatting

Flag / FilterDescription
-r (--raw-output)Output raw strings without JSON quotes
-c (--compact-output)Single-line compact JSON output
-S (--sort-keys)Sort object keys alphabetically in output
-e (--exit-status)Exit 1 if last output is false or null
-n (--null-input)Don't read input — useful with --argjson or inputs
-s (--slurp)Read entire input into single array
@csvFormat array as CSV row
@tsvFormat array as TSV row
@htmlHTML-escape a string
@uriPercent-encode a string for URLs
@base64Base64-encode a string
@base64dBase64-decode a string
@jsonSerialize value as JSON string

How Do You Pass External Variables into jq?

FlagDescription
--arg name valuePass a string variable: jq --arg v "hello" '$v'
--argjson name valuePass a JSON value: jq --argjson n 42 '$n + 1'
--slurpfile name fileLoad JSON file into variable as array
--rawfile name fileLoad file contents as raw string
--jsonargsTreat remaining args as JSON values (accessible via $ARGS.positional)
$ENV.VAR_NAMERead environment variable inside jq expression
env.VAR_NAMEAlternative syntax for environment variables

Recursive Descent and Path Expressions

ExpressionDescription
..Recursively descend through all values
.. | .name? // emptyFind all "name" fields at any depth
.. | objects | select(has("id"))Find all objects with an "id" key anywhere
path(..) | select(length > 0)List all paths in the document
getpath(["a","b"])Get value at path .a.b
setpath(["a","b"]; 42)Set value at path .a.b to 42
delpaths([["a","b"]])Delete the path .a.b
leaf_pathsList all paths to leaf (non-container) values

Frequently Asked Questions

How do you pretty-print JSON with jq?

Pipe your JSON into jq with no filter: echo '{"a":1}' | jq . — This formats the JSON with indentation and syntax highlighting.

How do you extract a field from every object in a JSON array?

Use the pattern jq '.[].fieldname' or jq '[.[] | .fieldname]' to collect results back into an array. For example: jq '[.[] | .name]' extracts the "name" field from every object.

What is the difference between map() and .[] | expression?

They produce the same results, but map(f) wraps the output back into an array automatically. Using .[] | f produces multiple separate outputs. Use map() when you want an array result; use .[] | f when piping into further filters.

How do you handle null or missing keys in jq?

Use the alternative operator // to provide defaults: .name // "unknown". Use the optional operator ? to suppress errors: .foo? avoids an error if the input is not an object. Use select(. != null) to filter out nulls.

How do you merge two JSON files with jq?

Use jq -s '.[0] * .[1]' file1.json file2.json — the --slurp flag reads both files into an array, and the * operator performs a recursive (deep) merge. For shallow merge, use + instead of *.

How do you convert JSON to CSV with jq?

First extract headers, then format rows: jq -r '(.[0] | keys_unsorted) as $k | $k, (.[] | [.[$k[]]] ) | @csv' data.json. The @csv formatter handles quoting and escaping automatically.