Docs / Queries
jq queries
Last updated:
jq is a query language for JSON. Prettify has a built-in jq engine, so you can filter, reshape, and extract data without leaving the editor. This page shows how to open the jq panel, run a query, apply the result, and which functions the engine supports. The jq panel is a Pro feature. Free users get one free try of it per day.
Prettify's jq engine runs on your device. It is a custom engine, not a WebAssembly port of the command-line tool. It matches jq 1.7 for the features listed here. The Learn jq by example post is a longer tutorial on the same engine.
Open the jq panel
The jq panel works on JSON data. It also works on the parsed data of other structured formats, such as YAML. For CSV, the same button opens the SQL panel. For XML, it opens the XPath panel.
Open the panel in one of two ways:
- In the toolbar, select
jq(in the Transform group). - Open the Command Palette with
Cmd+K(Mac) orCtrl+K(Windows, Linux), then runQuery / Transform.
The panel title is Query / Transform. A Pro badge marks the toolbar button for free users.
Run a query
Type a jq expression in the input field. The engine evaluates it as you type. The Source pane shows your document. The Result pane shows the output.
The panel gives you three ways to build a query:
Quickbuttons insert common expressions for your data.- The
Guidelists example expressions, including some based on your loaded fields. - The
Wizardbuilds a query from a field, an operator, a sort, and selected keys. It writes the jq into the input field, so you can read and edit it.
Recent shows queries you ran while the panel is open. The panel also keeps your last query for the session, so it returns when you reopen the panel. Prettify does not save queries to disk.
The Result pane shows the output as a stream, the same way the jq command prints it. Each value the query returns is pretty-printed on its own, one after another. The pane title shows the count, for example 2 results. A query that returns nothing, such as empty, shows No results.
A long stream shows its first 5,000 lines. The pane tells you how many lines are hidden.
Select Copy above the Result pane to copy the output to the clipboard. The copied text is the same text jq prints, with the values separated by new lines. Copy always copies the whole stream, including hidden lines.
Apply a result to the document
The result can replace your current document. This is useful when a query cleans or reshapes the data.
- Run a query that returns the data you want.
- Select
Apply, or pressCmd+Enter(Mac) orCtrl+Enter(Windows, Linux). - Confirm
Replace current data?in the dialog.
What Apply writes depends on the number of results:
- One result replaces the document with that value.
- Several results replace the document with one JSON array of the values. The dialog tells you how many results it holds.
- No results leaves
Applyturned off, because there is no value to write.
The old document is replaced by the result. Use History to go back to an earlier version.
How jq works
A jq expression reads a stream of values and returns a stream of values. The stream can hold zero, one, or many values.
.is the whole document..fieldreads a field. A missing field givesnull, not an error..[]opens an array or object and emits each element as a separate value.|pipes each value on the left into the expression on the right.,runs two expressions on the same input and joins their outputs.
The engine uses these core forms: field and index access, slices, iteration, the pipe, comparison and arithmetic operators, and, or, not, the alternative operator //, the optional operator ?, object and array construction, if ... then ... elif ... else ... end, reduce, foreach, try ... catch, as bindings, the assignment operators, format strings, and string interpolation \(...).
Change values with assignment
Assignment returns the whole document with some values changed. The left side names the values to change, and the right side gives the new value. Select Apply to write the result back to your document.
| Operator | Example | Result |
|---|---|---|
= | .status = "done" | Sets status to "done". The right side reads the whole document, so .total = .subtotal copies one field to another. |
|= | .name |= ascii_upcase | Runs the right side on the current value of name and stores the result. |
+=, -=, *=, /=, %= | .items[].price *= 1.1 | Does the arithmetic on each value the left side names. |
//= | .role //= "member" | Sets role only when it is null or false. |
The left side can name many values at once, for example .items[].price or (.[] \| select(.active) \| .score). A path that does not exist yet is created, so .meta.updated = true adds meta when it is missing. With |=, a right side that returns nothing deletes the value: .tags[] |= select(. != "old") removes every "old" tag.
Cookbook
Every example below uses this document:
{
"company": "Acme",
"employees": [
{ "name": "Alice", "age": 30, "role": "CEO", "email": "alice@acme.com", "salary": 185000 },
{ "name": "Bob", "age": 25, "role": "CTO", "email": "bob@acme.com", "salary": 170000 },
{ "name": "Carol", "age": 35, "role": "Designer", "email": "carol@acme.com", "salary": 125000 }
]
}
Read one field:
.company
Count the array:
.employees | length
Collect one field from each element:
.employees | map(.name)
Filter the stream, then take a field:
.employees[] | select(.age > 25) | .name
Filter but keep an array:
.employees | map(select(.age > 25))
Sort by a field:
.employees | sort_by(.age)
Find the highest and lowest:
.employees | max_by(.age)
Sum and average a field:
.employees | map(.salary) | add / length
Deduplicate values:
.employees | map(.role) | unique
Group by a field, then count the groups:
.employees | group_by(.role) | length
Join names into one string:
.employees | map(.name) | join(", ")
Pick fields into a new object:
.employees | map({ name, salary })
Rename fields:
.employees | map({ label: .name, pay: .salary })
Get the unique email domains:
.employees | map(.email | split("@") | .[1]) | unique
Give a default for a missing field:
.manager // "none"
Sum with reduce:
reduce .employees[] as $e (0; . + $e.age)
Build a sentence with a variable:
.employees | length as $n | "\($n) employees"
Functions and destructuring
Define your own function with def. End the definition with a semicolon. The query continues after it:
def double: . * 2; .employees | map(.age | double)
A function can take parameters. A plain name is a filter: the caller passes an expression, and the function runs it on its own input. A name with a $ is a value: the function gets each output of the argument. Separate parameters with semicolons:
def raise($pct): . * (1 + $pct / 100); .employees | map(.salary | raise(10))
def each(f): [.[] | f]; .employees | each(.name)
A function can call itself:
def fac: if . <= 1 then 1 else . * (. - 1 | fac) end; 5 | fac
A function name includes its number of parameters, so f and f(x) are different functions. A new definition replaces an older one with the same name and number of parameters, including a built-in function. Definitions can be nested. A function sees the variables that exist where you define it.
User-defined functions also work where jq needs a path, such as assignment, path(), and del():
def price: .items[].price; price |= . * 2
Destructuring binds several variables with one as. Use an array pattern or an object pattern. A missing element or field gives null:
.point as [$x, $y] | $x + $y
.user as {name: $n, tags: [$first]} | "\($n) \($first)"
{$name} is short for {name: $name}. A key can also be a string or an expression in parentheses, such as {(.key): $v}. Patterns also work in reduce and foreach:
reduce .items[] as {price: $p} (0; . + $p)
Join patterns with ?// to try one after another. If a pattern fails, or the body raises an error with it, jq uses the next pattern. Every variable of every pattern exists in the body, and it is null when its pattern did not bind it:
.[] as [$a] ?// {a: $a} | $a
Numbers
Prettify preserves JSON numbers byte for byte, even very large integers and high-precision decimals. A query that reads or copies a number keeps it exact.
Arithmetic, aggregation, and comparison convert a number to a standard floating-point value first. This can change digits in a very large or very precise number. When it happens, the Result pane shows a note that the result is approximate. The original value in the document stays exact.
Differences from jq 1.7
The engine covers normal jq use. Some features behave differently:
- Recursion in user-defined functions has a depth limit, because the browser stack is small. Very deep recursion ends with the error
function call nesting too deep. jq has no such limit. - The query has one input document.
inputsproduces nothing, andinputraises the errorNo more inputs. envand$ENVreturn an empty object, because the browser has no process environment.input_line_numberreturns0, andinput_filenameandmodulemetareturnnull. jq returns"<stdin>"forinput_filenamewhen it reads standard input.stderrpasses its input through and writes a copy to the browser console. jq writes it to standard error.- A field name used on an array, such as
.items.price, maps over the elements and returns an array. jq raises an error..[]onnullproduces nothing, and jq raises an error. - Number output follows JSON.
infiniteand-infiniteshow asnull, where jq prints the largest double. jq also keeps the written form of a number literal such as1e3, and Prettify prints1000. trimandtoarrayare extra functions that jq 1.7.1 does not have.@jsondoes not escape the character U+007F, and jq does.tryand?do not catchbreak $name. The break stops itslabel, as the jq manual describes. jq 1.7.1 letstrycatch a break.- Regular expressions use the JavaScript engine, not Oniguruma.
test,match,capture,scan,split,splits,sub, andgsubaccept the jq modifiersg,i,x,n,s, andp, and convert\A,\z,\Z, POSIX classes such as[[:alpha:]], and a leading(?i). Other Oniguruma syntax follows JavaScript rules. The modifierl(longest match) has no effect, andnskips empty matches instead of looking for a non-empty match at the same place. Error messages for an invalid pattern come from the JavaScript engine.
Supported functions
The engine registers the jq 1.7 builtin library. The tables below group the functions by purpose.
Core and inspection
| Function | Purpose |
|---|---|
type | Name the type of a value. |
length | Length of a string, array, or object. |
has, in | Test for a key or index. |
contains, inside | Test containment. |
empty | Produce no output. |
error | Raise an error. |
not | Invert a boolean. |
isempty | Test whether an expression is empty. |
builtins | List the builtin names. |
debug, stderr | Pass the value through. |
halt, halt_error | Stop with an error. |
$__loc__ | The file and line of the expression. |
Type filters
arrays, objects, iterables, booleans, numbers, strings, nulls, values, scalars, null. Each emits its input when the input matches the type, and nothing otherwise. values emits every non-null input. null produces a null value.
Selection and traversal
select, map, map_values, recurse, walk, paths, leaf_paths, path, getpath, setpath, delpaths, del, pick.
Arrays
add, any, all, flatten, range, reverse, sort, sort_by, group_by, unique, unique_by, min, max, min_by, max_by, first, last, nth, limit, repeat, until, while, transpose, indices, index, rindex, bsearch, combinations, JOIN, toarray.
Objects
keys, keys_unsorted, to_entries, from_entries, with_entries, values.
Strings
ascii_downcase, ascii_upcase, ltrimstr, rtrimstr, trim, split, splits, join, test, match, capture, scan, sub, gsub, startswith, endswith, explode, implode, ascii.
Numbers and math
abs, fabs, floor, ceil, round, trunc, rint, nearbyint, sqrt, cbrt, pow, exp, exp2, exp10, expm1, log, log2, log10, log1p, sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanh, hypot, fmin, fmax, fmod, fma, fdim, drem, remainder, copysign, ldexp, scalb, scalbln, significand, logb, frexp, modf, nan, infinite, isnan, isinfinite, isnormal, isfinite, finites, normals, tonumber.
Conversion and encoding
tostring, tojson, fromjson, format, utf8bytelength, @text, @json, @html, @uri, @csv, @tsv, @sh, @base64, @base64d, @base32, @base32d. A format before a string, such as @base64 "x\(.a)", formats each interpolated value and leaves the text unchanged.
Dates and time
now, gmtime, localtime, mktime, strftime, strflocaltime, strptime, todate, fromdate, todateiso8601, fromdateiso8601.
Streaming
tostream, fromstream, truncate_stream, IN, INDEX.
Related pages
Try it online
Tool pages for this topic. Each one runs in your browser.