Processing JSON with jq
By the end of this lesson you'll be able to slice, filter, and reshape JSON straight from the terminal with jq — pulling out fields, iterating arrays, filtering with conditions, and feeding a live API response from curl into a clean, scriptable result.
Learn Processing JSON with jq in our free Command Line course — an interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Cli course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
1. The Identity Filter & Accessing Fields
jq is a dedicated JSON processor with its own little filter language — it is not bash. You pipe JSON into it and give it a filter wrapped in single quotes (the quotes stop the shell from touching it). The simplest filter is . , the identity filter : it returns the input unchanged and pretty-prints it. To pull out a field, write .key — for example .name . Strings come back with their JSON quotes.
2. Reaching Into Nested Objects
JSON nests objects inside objects. To dig in, just chain the keys : .a.b.c . So .address returns the whole address object, and .address.city reaches one level deeper to the city inside it. Each dot steps down one level.
3. Arrays: Index With .[0] and Iterate With .[]
For arrays, .[n] grabs a single element by its zero-based index — .[0] is the first, .[2] the third. To process every element, use .[] : it iterates , emitting each element as its own separate result. Put it after a field — .colors[] — to walk an array that lives inside an object.
4. Raw Output With -r
By default jq prints strings as valid JSON, so a name comes out as "Ada" — quotes and all. The -r ( raw ) flag strips those quotes and prints Ada . That's exactly what you want when piping a value into another command or capturing it in a shell variable. Combine -r with .[] to get a clean, plain list.
5. Piping Filters: select and map
Inside a filter, jq has its own pipe | that feeds one filter's output into the next. select(condition) passes its input through only when the condition is true, so .[] | select(.age > 30) keeps just the matching records. map(f) applies a filter to every element of an array and collects the results into a new array — map(.price * 2) doubles each price.
6. keys, length, Building Objects & curl
keys returns an object's keys as a sorted array ; length gives an array's element count, a string's character count, or an object's number of keys. You can build a brand-new object with {' name: .name, id: .id '} , keeping only the fields you care about. And the payoff: pipe a live response from curl straight into jq, e.g. curl -s URL | jq '.results[].name' .
Fill in the blank marked ___ using the # 👉 hint, then run it and check the Output panel matches.
Two blanks: the filter that iterates an array, and the comparison that means "18 or more". Then run it.
No blanks this time — just a brief and some hints. Given a JSON array of products, count them, list their names cleanly, and rebuild the pricier ones into trimmed objects. Check your output against the example in the comments.
Practice quiz
What is jq?
- A dedicated command-line JSON processor with its own filter language
- A bash built-in command
- A web browser
- A JavaScript runtime
Answer: A dedicated command-line JSON processor with its own filter language. jq is a standalone tool for slicing, filtering, and transforming JSON. Its filter language is its own — it is not bash.
Which filter is the identity filter that passes the input through unchanged (and pretty-prints it)?
- @
- *
- .
- id
Answer: .. The single dot . is the identity filter: it returns the input as-is and jq pretty-prints it by default.
How do you access the field named name on a JSON object?
- name()
- .name
- get(name)
- ->name
Answer: .name. A field is accessed with .name, for example echo '{"name":"Ada"}' | jq '.name'.
What does the filter .[] do?
- Deletes the array
- Returns the array length
- Sorts the array
- Iterates over the elements of an array (or values of an object)
Answer: Iterates over the elements of an array (or values of an object). .[] iterates: it produces each element of an array as a separate output value.
What does the -r flag do?
- Outputs raw strings without surrounding quotes
- Reads from a file
- Repeats the filter
- Reverses the output
Answer: Outputs raw strings without surrounding quotes. -r (raw output) prints string results without the surrounding double quotes, which is ideal for shell pipelines.
Why are jq filters usually wrapped in single quotes?
- It is only a style preference with no effect
- To stop the shell from expanding or mangling characters like $, *, and spaces in the filter
- To make jq run faster
- Single quotes are required to define a variable
Answer: To stop the shell from expanding or mangling characters like $, *, and spaces in the filter. Single quotes protect the filter from the shell so jq receives it verbatim.
What does keys return when given a JSON object?
- The number of keys
- The values only
- The first key as a string
- The object's keys as a sorted array
Answer: The object's keys as a sorted array. keys returns the object's keys as an array, sorted alphabetically.
What does length return for a JSON array?
- The first element
- Always 1
- The number of elements in the array
- The array reversed
Answer: The number of elements in the array. For an array, length is the element count; for a string it is the character count; for an object it is the number of keys.
Which filter keeps only the items where age is greater than 30?
- filter(age, 30)
- select(.age > 30)
- where .age > 30
- keep(.age)
Answer: select(.age > 30). select(condition) passes its input through only when the condition is true, e.g. select(.age > 30).
What does map(.price * 2) do to an input array?
- Returns a new array with each element's price doubled
- Returns only the first price
- Sorts the array by price
- Deletes the price field
Answer: Returns a new array with each element's price doubled. map(f) applies the filter f to every element of an array and collects the results into a new array.