Every entry below is a jq filter, what it returns, and a minimal example. Output shown came from jq 1.8.2. For the guided version with explanations and larger worked examples, read the [jq Cookbook][learn-jq]. ## Run Any Entry Here The runner holds the same `employees.json` used throughout this reference. Paste any filter from the entries below into the filter box and press Run. { "company": "Acme", "employees": [ { "id": 1, "name": "Ada Lopez", "email": "ada@acme.example", "dept": "Engineering", "age": 34, "salary": 145000, "skills": ["go", "sql"], "manager": null }, { "id": 2, "name": "Ben Okafor", "email": "ben@acme.example", "dept": "Engineering", "age": 28, "salary": 118000, "skills": ["python"], "manager": 1 }, { "id": 3, "name": "Chen Wu", "email": "chen@contractor.example", "dept": "Design", "age": 41, "salary": 99000, "skills": ["figma", "css"], "manager": 1 }, { "id": 4, "name": "Dana Smith", "email": "dana@acme.example", "dept": "Sales", "age": 25, "salary": 72000, "skills": [], "manager": 3 } ] } ## Selecting Values The identity filter and field access. These cover most single-value lookups. * `.` returns the whole input unchanged. Use it to pretty-print. * `.company` returns one field. Returns `null` when the key is absent. * `."odd key"` returns a field whose name contains spaces or punctuation. * `.a.b.c` walks nested objects. Any missing level yields `null`. * `.a?` suppresses the error when the input is not an object. * `.employees[]` emits each array element as a separate result. * `.employees[0]` returns one element by index. Indexes start at 0. * `.employees[-1]` counts from the end. * `.employees[1:3]` slices from index 1 up to but excluding index 3. * `..` recurses through every value in the document. ```bash jq -r '.employees[0].name' employees.json ``` ```text Ada Lopez ``` ## Filtering With select `select(condition)` passes an input through when the condition is true and emits nothing when it is false. * `select(.age > 30)` keeps matching values. * `select(.dept == "Design")` compares for equality. * `select(.age > 30 and .dept == "Engineering")` combines with `and`, `or`, and `not`. * `select(.name | test("^[ab]"; "i"))` matches a regular expression. The second argument holds flags, where `i` means case-insensitive. * `select(.skills | index("go"))` keeps values whose array contains a member. * `select(.manager == null)` finds explicit nulls. * `select(has("email"))` tests for a key rather than a value. `not` is a filter, so it follows a pipe rather than preceding the expression. ```bash jq -r '.employees[] | select(.age > 30) | .name' employees.json ``` ```text Ada Lopez Chen Wu ``` ## Reshaping Objects Build a new object, or edit the one you have. * `{name, dept}` keeps only those fields, using the field names as keys. * `{n: .name, d: .dept}` renames fields. * `.name = "New"` sets a value. * `.age |= . + 1` updates a value with a filter. * `. + {active: true}` merges an object, with the right side winning on conflicts. * `del(.email)` removes a key. * `with_entries(select(.value != null))` drops null-valued keys. * `keys` returns sorted key names, and `keys_unsorted` preserves document order. * `to_entries` converts an object to an array of `{key, value}` pairs, and `from_entries` reverses it. ```bash jq -c '.employees[0] | {n: .name, d: .dept}' employees.json ``` ```text {"n":"Ada Lopez","d":"Engineering"} ``` ## Arrays and Aggregation Collect, count, and summarize. * `[.employees[].name]` wraps a stream back into an array. * `length` returns array length, object key count, or string character count. * `map(.salary)` applies a filter to every element. * `add` sums numbers, concatenates strings, or merges objects. * `min`, `max`, `min_by(.age)`, and `max_by(.age)` find extremes. * `sort` orders an array, and `sort_by(.age)` orders by a computed key. * `reverse` flips order. Combine with `sort_by` for descending order. * `unique` removes duplicates and sorts, and `unique_by(.dept)` deduplicates on a key. * `group_by(.dept)` returns an array of arrays, grouped by a sorted key. * `flatten` collapses nested arrays, and `flatten(1)` limits the depth. * `any` and `all` test a whole array, returning a single boolean. * `range(0; 5)` generates numbers, including the start and excluding the end. `add` on an empty array returns `null`, so guard totals with `// 0` when the input may be empty. ```bash jq '[.employees[].salary] | add' employees.json ``` ```text 434000 ``` ## Strings and Numbers Convert, format, and interpolate. * `tostring` and `tonumber` convert between types. `tonumber` fails on text that is not numeric. * `ascii_downcase` and `ascii_upcase` change case for ASCII only. * `ltrimstr("pre")` and `rtrimstr(".suf")` remove a prefix or suffix when present. * `split(",")` divides a string into an array, and `join(", ")` reverses it. * `test("regex")` returns a boolean, `match("regex")` returns match details, and `capture("(?re)")` returns named groups. * `sub("a"; "b")` replaces the first match, and `gsub("a"; "b")` replaces every match. * `"Hi \(.name)"` interpolates a filter into a string. * `floor`, `ceil`, `round`, `fabs`, and `sqrt` cover common arithmetic. * `now` returns the current Unix timestamp, and `todate` formats one as ISO 8601. ```bash jq -r '.employees[] | "\(.name) <\(.email)>"' employees.json | head -2 ``` ```text Ada Lopez Ben Okafor ``` ## Defaults and Error Handling Keep a filter running when the data is imperfect. * `.missing // "fallback"` substitutes when the left side is `null` or `false`. * `.a?` returns nothing instead of erroring when the input type is wrong. * `try .a catch "bad"` catches an error and returns a replacement. * `error("message")` raises an error deliberately. * `empty` produces no output, which removes a value from a stream. * `halt_error` exits with a non-zero status, which is useful in scripts. `//` treats `false` as absent, so it is the wrong operator for a boolean field that may legitimately be `false`. ```bash jq '.employees[0].address.city // "unknown"' employees.json ``` ```text "unknown" ``` ## Output Formats Control what reaches stdout. * `@csv` formats an array as one comma-separated row, quoting strings. * `@tsv` formats an array as a tab-separated row. * `@json` serializes a value as a JSON string. * `@base64` encodes, and `@base64d` decodes. * `@uri` percent-encodes for use in a URL. * `@sh` quotes a value for safe use in a shell command. `@csv` and `@tsv` require an array of scalars, so build one with `[...]` first, and pair them with `-r` to strip the outer quotes. ```bash jq -r '.employees[] | [.name, .dept, .salary] | @csv' employees.json | head -2 ``` ```text "Ada Lopez","Engineering",145000 "Ben Okafor","Engineering",118000 ``` ## Command-Line Flags Flags change how jq reads input and writes output. * `-r` prints strings raw, without surrounding quotes. * `-j` prints raw output with no trailing newline. * `-c` prints each result on a single line. * `-n` starts with `null` input instead of reading stdin, which suits `--arg`-only invocations. * `-s` reads the entire input stream into one array. * `-e` sets the exit status from the output, returning 1 when the result is `null` or `false`. * `-S` sorts object keys in the output. * `--tab` indents with tabs, and `--indent N` sets a space count from 0 to 7. * `--arg name value` passes a string variable, available as `$name`. * `--argjson name value` passes parsed JSON rather than a string. * `--slurpfile name file` reads a file into an array variable, and `--rawfile` reads it as one string. * `--raw-input` treats each input line as a string instead of JSON. * `-f file.jq` reads the filter program from a file. Always pass shell values through `--arg` rather than string-concatenating them into the program, which keeps quoting correct. ```bash jq -n --arg dept Design --argjson min 90000 \ '{dept: $dept, floor: $min}' ``` ```text { "dept": "Design", "floor": 90000 } ``` ## Error Messages and What They Mean The text jq prints on stderr, and the usual cause. * `jq: error: syntax error, unexpected ...` means the filter failed to compile. Check for an unclosed bracket or quote. * `Cannot index array with string ("name")` means a `.field` was applied to an array. Add `[]` to iterate first. * `Cannot index string with string ("name")` means the value is a string, often because `-r` output was piped back into jq. * `Cannot iterate over null` means `[]` was applied to a missing key. Use `.a[]?` to skip it. * `null (null) has no keys` means `keys` ran against a missing object. * `Cannot index number with number (0)` means an index was applied to a scalar. * `parse error: Invalid numeric literal` means the input is not valid JSON. Check for a shell prompt or log line mixed into the stream. * `jq: error (at :1)` prefixes runtime errors, where the number is the input line. jq exits 0 on success, 1 when `-e` is set and the output is `null` or `false`, 2 on a usage problem, 3 on a compile error, and 5 after `halt_error`. ## Related Reading * The [jq Cookbook][learn-jq] covers the same filters with explanations and full worked examples. * The [jq Manual][jq-manual] is the authoritative specification for every builtin. ## References * [jq Manual][jq-manual], the official reference for jq 1.8, covering every builtin, operator, and flag. * [jq on GitHub][jq-github], for release notes and the changelog that records behavior changes between versions. [learn-jq]: https://jeffbailey.us/blog/2021/11/30/learn-jq/ [jq-manual]: https://jqlang.org/manual/ [jq-github]: https://github.com/jqlang/jq