Answer: jq is a command-line JSON processor, and a filter like .order.items | map(.qty * .price) | add sums a cart: on the sample below that's 728, plus $18.50 shipping = 746.50. This playground runs jq 1.8.2 — compiled to WebAssembly from the official jqlang/jq source — so filters, flags, and error messages match the CLI exactly. Output updates as you type, and your JSON never leaves the page.

JSON In, Filter, Result Out loading engine…

Ad
Ad

Why does my filter print each result on its own line instead of an array?

Because jq works on streams. A filter like .order.items[] | .sku produces three separate outputs, and jq prints each one on its own line. Wrap the whole thing in square brackets, as in [.order.items[] | .sku], to collect them into one array. Use the bare stream when a shell loop reads the output line by line, and the array when you need valid JSON.

How do I get plain text without quotes from jq?

Tick the -r box, which matches jq's --raw-output flag. Strings then print without their surrounding quotes, so "Desk Mat" becomes Desk Mat, which is what you want when the output goes into a shell variable or a CSV. Numbers, objects and arrays look the same either way. The report-lines example turns -r on for you.

jq Filter Cheat Sheet

FilterWhat it doesOn the sample order
.Identity — the input unchangedthe whole order object
.order.customer.nameWalk a path"Dana Reyes"
.order.items | lengthCount array elements3
.order.items[]Stream every element3 separate item objects
.order.items[] | .qty * .priceArithmetic per element129, 549, 50
map(.qty * .price) | addCollect then sum728
select(.price > 100)Keep matching valueskeyboard + desk
sort_by(-(.qty * .price)) | .[0]Order and indexthe standing desk
keysArray of an object's keys["order"]
to_entriesObject → key/value array5 entries: id, customer, items…
[.order.items[].price] | min, maxStatistics on collected values25 and 549
"\(.sku): \(.qty) x $\(.price)"String interpolationKB-01: 1 x $129
.missing // "none"Alternative for null/false"none"

Every value in the right column was produced by this page's engine on the default sample — click the chips above to reproduce each one.

How the jq Playground Works

jq, written by Stephen Dolan and maintained today as jqlang/jq (MIT license), is the JSON processor: a tiny language for slicing, filtering, and reshaping JSON that has become the connective tissue of shell pipelines everywhere. The official playground at jqplay.org inspired this page's layout — JSON on the left, filter in the middle, live output — but here the engine runs in your tab: jq 1.8.2 compiled to WebAssembly through the MIT-licensed jq-wasm build, roughly 900 KB fetched once from the jsDelivr CDN. After that, every keystroke re-runs your filter locally.

Filters are pipelines

The mental model is a Unix pipe. .order.items selects a value; | length feeds that value to the length function; [] explodes an array into a stream where each element runs through whatever follows. Because filters are values too, map(f) is just [.[] | f] with a name. That composability is why one-liners like .items | map(select(.qty > 0)) | map(.qty * .price) | add read left to right as a sentence.

How to use it

Paste any JSON on the left, type a filter, and the output pane updates as you type. The checkboxes map to the CLI flags you'd actually use: -r for unquoted strings, -c for one-line compact output, -S for sorted keys. Errors appear verbatim from jq's own stderr with the exit code, which is precisely what you'd see in a terminal — useful when you're debugging a filter for a script. The chips load worked filters against the sample order.

A worked example

The sample document is one order: three line items (keyboard $129, standing desk $549, two desk mats at $25) and $18.50 express shipping. Start simple: .order.items | length is 3. Multiply per line: .order.items[] | .qty * .price streams 129, 549, 50. Sum with map(.qty * .price) | add to get the subtotal 728, then bind it and add shipping — .order as $o | ($o.items | map(.qty * .price) | add) + $o.shipping.cost — for the 746.50 total. Interpolation turns the items into report lines: .order.items[] | "\(.sku): \(.qty) x $\(.price)" prints KB-01: 1 x $129 and friends under the -r flag. Average unit price divides 728 by 4 total units: 182 exactly.

jq Cheat Sheet, Tested on the Sample Order

Every filter below runs against the sample JSON that loads with the page, and the output column is exactly what you'll get with the -c flag on. Paste any of them into the filter box to see it work.

GoalFilterOutput
List an object's keys.order | keys["coupons","customer","id","items","shipping"]
Last element of an array.order.items[-1].sku"MAT-02"
Collect one field into an array[.order.items[].sku]["KB-01","DSK-04","MAT-02"]
Count matches.order.items | map(select(.qty > 1)) | length1
Cheapest item.order.items | sort_by(.price) | .[0].name"Desk Mat"
Build a lookup object.order.items | map({(.sku): .price}) | add{"KB-01":129,"DSK-04":549,"MAT-02":25}
Join strings.order.customer.emails | join(", ")"[email protected], [email protected]"
Default for a missing field.order.discount // "none""none"
Match on a string prefix.order.items[] | select(.sku | startswith("D")) | .sku"DSK-04"
Drop a field.order | del(.coupons) | keys["customer","id","items","shipping"]
Count every number in the document[paths(type == "number")] | length8

Two patterns cover most real work. select() keeps only what matches, and map() reshapes every element. Wrap a stream in [ ] when you want an array back, and leave it bare when you want one result per line, which is what shell loops expect.

How is this different from jq on the command line?

It's the real jq, compiled to WebAssembly, so filters behave the same way. The differences come from how your JSON reaches it. The page reads the left-hand box with the browser's JSON parser and hands jq a single document.

Your JSON stays in the tab. The engine downloads once from the CDN, and after that every run happens on your machine, which makes the playground fine for API responses with tokens or customer data in them.

Frequently Asked Questions

What is a jq playground good for?

It lets you test jq filters against sample JSON instantly, showing output and errors side by side without installing jq locally. This is the fastest way to learn filter syntax or debug a filter before putting it in a script. Everything runs in your browser, so your data never leaves the machine.

Do all jq filters work in a browser jq playground?

Most core filters — selection, projection, iteration, arithmetic, string interpolation, and common builtins — behave the same as the command-line tool. Features that need the filesystem or network, such as --slurpfile or curl-fed inputs, are naturally absent. Edge cases in newer jq versions may differ depending on the bundled build.

Why use jq in the playground instead of a Python script for JSON?

jq is a declarative language purpose-built for JSON transformation, so common operations are one-liners compared to several lines of Python parsing and error handling. A Python script is better when the task needs state, external libraries, or non-JSON logic. Many pipelines use jq for the shaping step and a script only when logic gets complex.