Quick reference for jq: basic filters, pipes, selectors, string operations, array and object manipulation, reduce, path expressions, output formatting, and passing variables.
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
| Filter | Description |
|---|
| . | Identity — pretty-print the entire input |
| .foo | Access object key "foo" |
| .foo.bar | Access 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?
| Expression | Description |
|---|
| .foo | .bar | Pipe — feed output of left filter into right filter |
| .foo, .bar | Comma — output both values (multiple outputs) |
| .[] | .name | Iterate 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
| Operator | Description |
|---|
| ==, != | Equality and inequality |
| <, <=, >, >= | Numeric/string comparison |
| and, or, not | Boolean logic operators |
| if .x then .y else .z end | Conditional expression |
| // "default" | Alternative operator — use right value if left is null or false |
| .x // empty | Suppress null values (emit nothing instead) |
How Do You Filter and Select Elements?
| Expression | Description |
|---|
| 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) | .price | Extract field only from objects that have it |
String Operations
| Expression | Description |
|---|
| "Hello, \(.name)!" | String interpolation using \( ) |
| ascii_downcase | Convert to lowercase |
| ascii_upcase | Convert 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 |
| length | String length (also works on arrays/objects) |
| startswith("http") | Check if string starts with value |
| endswith(".json") | Check if string ends with value |
Array Operations
| Expression | Description |
|---|
| map(.price * 2) | Apply expression to every element |
| map_values(. + 1) | Apply expression to every value in an object |
| sort | Sort array (numbers/strings) |
| sort_by(.name) | Sort array of objects by a key |
| reverse | Reverse an array |
| unique | Remove duplicates |
| unique_by(.id) | Remove duplicates by a key |
| flatten | Flatten 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 |
| add | Sum 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 |
| [., .[]] | length | Length of the array |
Object Operations
| Expression | Description |
|---|
| keys | Get array of object keys (sorted) |
| keys_unsorted | Get array of object keys (original order) |
| values | Get 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_entries | Convert {k:v} to [{key:k, value:v}, ...] |
| from_entries | Convert [{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
| Expression | Description |
|---|
| [.[] | .price] | add | Sum a specific field across array of objects |
| length | Count elements in array or keys in object |
| [.[] | .score] | add / length | Calculate 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
| Expression | Description |
|---|
| type | Return type as string: "object", "array", "string", "number", "boolean", "null" |
| tostring | Convert value to string |
| tonumber | Convert string to number |
| arrays, objects, strings, numbers, booleans, nulls | Select only values of that type |
| not | Boolean negation |
| empty | Produce no output (useful in conditionals) |
| null | Literal null value |
| error("msg") | Abort with error message |
| try .foo catch "fallback" | Try expression, use fallback on error |
| try .foo | Silently suppress errors (same as .foo?) |
Output Formatting
| Flag / Filter | Description |
|---|
| -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 |
| @csv | Format array as CSV row |
| @tsv | Format array as TSV row |
| @html | HTML-escape a string |
| @uri | Percent-encode a string for URLs |
| @base64 | Base64-encode a string |
| @base64d | Base64-decode a string |
| @json | Serialize value as JSON string |
How Do You Pass External Variables into jq?
| Flag | Description |
|---|
| --arg name value | Pass a string variable: jq --arg v "hello" '$v' |
| --argjson name value | Pass a JSON value: jq --argjson n 42 '$n + 1' |
| --slurpfile name file | Load JSON file into variable as array |
| --rawfile name file | Load file contents as raw string |
| --jsonargs | Treat remaining args as JSON values (accessible via $ARGS.positional) |
| $ENV.VAR_NAME | Read environment variable inside jq expression |
| env.VAR_NAME | Alternative syntax for environment variables |
Recursive Descent and Path Expressions
| Expression | Description |
|---|
| .. | Recursively descend through all values |
| .. | .name? // empty | Find 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_paths | List 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.