jq Tutorial: Query and Transform JSON on the Command Line
Learn jq, the command-line JSON processor: the identity filter, the pipe, selecting fields, filtering with select, transforming arrays with map, and building new objects — with copyable examples.
jq is to JSON what grep, sed, and awk are to text: a small, fast command-line tool for slicing, filtering, and reshaping JSON. Once it clicks, you stop writing throwaway scripts to pull a field out of an API response. This tutorial builds jq up from the identity filter to real transformations, with examples you can paste and adapt.
The mental model: filters and streams
jq is built around filters that run over a stream of JSON. Each filter takes JSON input and emits JSON output, and you connect filters with the pipe operator just like in a Unix shell. Master that one idea — input flows through a chain of small filters — and the rest of jq is just learning which filters exist.
The identity filter and pretty-printing
The simplest filter is . (a single period), the identity filter: it passes input through unchanged. Running curl ... | jq '.' formats and colorizes a JSON response, which alone makes jq worth installing. From there, . is also the starting point for navigation: .name reads the name field, and .user.email walks into nested objects.
echo '{"name":"Ada","age":36}' | jq '.'Accessing fields and arrays
- .name — read a top-level field
- .user.email — read a nested field
- .items[0] — the first array element
- .items[] — stream every element of an array, one at a time
- .items[].name — the name of every element
Filtering with select
select takes a boolean condition and passes through only the inputs that match — it is the WHERE clause of jq. Combined with the array-streaming syntax, .items[] | select(.price < 10) emits only the items cheaper than ten. You can compose conditions with and, or, and not, and compare strings and numbers, making select the workhorse for extracting the records you care about.
echo '{"items":[{"price":5},{"price":20}]}' \
| jq '.items[] | select(.price < 10)'
# → {"price":5}Transforming with map and building objects
map applies a filter to every element of an array and rewraps the results, so map(.price) turns an array of objects into an array of prices. To reshape data, build a new object with curly braces: .items[] | {name: .name, cost: .price} emits a slimmed-down object for each item. The add filter sums an array of numbers, and length returns sizes — combine these to compute totals and summaries in one line.
jq 'map(.price)' # [5, 20]
jq '.items[] | {name, cost: .price}' # build new objectsCompact output and raw strings
Two flags come up constantly. The -c flag emits compact, one-line output — and since that is one JSON value per line, it is how you produce JSONL from jq. The -r flag outputs raw strings without quotes, which you want when piping a value into another shell command. Together, jq -r '.items[].name' prints each name on its own line, ready for a loop.
jq versus browser tools
jq shines for scripting and pipelines, but for a quick interactive look at a payload, a browser tool is faster. A JSON Path extractor runs queries against pasted JSON without the shell, a tree viewer lets you explore structure visually, and a formatter pretty-prints without installing anything. Use jq in your terminal workflows and the visual tools when you just need to read or probe a document.
Frequently asked questions
What is jq used for?
jq is a command-line JSON processor for filtering, transforming, and reshaping JSON. It is the JSON equivalent of grep, sed, and awk — commonly used to pull fields out of API responses, reformat data, and build pipelines in scripts.
How do I pretty-print JSON with jq?
Pipe JSON through the identity filter: jq '.'. It formats and colorizes the output. Add the -c flag instead for compact one-line output, which is also how you generate JSONL.
How do I filter JSON with jq?
Use select with a condition: .items[] | select(.price < 10) emits only matching elements. select is jq's equivalent of a WHERE clause, and you can combine conditions with and, or, and not.
What does map do in jq?
map applies a filter to every element of an array and rewraps the results into an array. For example, map(.price) extracts the price from each object, returning an array of prices.
What is the difference between jq -r and -c?
The -r flag outputs raw strings without surrounding quotes, which is useful when piping values into other shell commands. The -c flag produces compact one-line JSON output, ideal for generating JSONL or feeding other tools.
Related tools
Try these tools
JSON Path Extractor
Query JSON with dot paths and bracket indices — extract values at any key path.
JSON Formatter & Beautifier
Format, prettify, and beautify messy JSON with configurable indentation and key sorting.
JSON Viewer & Tree Explorer
Explore JSON with an interactive collapsible tree view.
JSON Validator
Validate JSON instantly with precise, human-readable error messages and line numbers.