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.

What You'll Learn

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' .

🎯 Your Turn: pull a nested field, raw

Fill in the blank marked ___ using the # 👉 hint, then run it and check the Output panel matches.

🎯 Your Turn: iterate and filter

Two blanks: the filter that iterates an array, and the comparison that means "18 or more". Then run it.

Pro Tips

Common Errors (and the fix)

📋 Quick Reference

Filter

Example

What it does

Identity

jq '.'

Input unchanged, pretty-printed

Field

jq '.name'

Value of a key

Nested

jq '.a.b'

Chain keys to go deeper

Index

jq '.[0]'

One element (zero-based)

Iterate

jq '.[]'

Each element separately

Pipe

jq '.[] | .name'

Feed one filter into the next

Filter

jq 'select(.age > 30)'

Keep only matching input

Transform

jq 'map(.price * 2)'

Apply to each, return array

Raw

jq -r '.name'

Strip the JSON quotes

Keys

jq 'keys'

Object keys, sorted array

Length

jq 'length'

Array len / string len / key count

Build

jq ' { n: .name } '

Construct a new object

Frequently Asked Questions

Mini-Challenge: summarise a product list

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.

🎉 Lesson Complete!

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.

Continue this course