Skip to content
← Writing

jq: JSON on the Command Line

A practical guide to jq: piping JSON in, pretty-printing, filtering and reshaping it, with the handful of expressions worth committing to memory.

  • 3 min read
Skip to contents
Contents
Illustration of jq: JSON on the Command Line

Pipe JSON in, get what you need out.

APIs return JSON. Config files are JSON. Logs are often JSON. jq is a small, fast command-line tool that lets you slice, filter, and transform that JSON without leaving the terminal. Once you know the basics, you’ll reach for it constantly.

This post covers piping JSON into jq, the core operations, and a few practical patterns.


Piping JSON into jq

The usual pattern: something produces JSON, you pipe it into jq.

From a string (e.g. for quick tests):

echo '{"name":"world"}' | jq

Output:

{
  "name": "world"
}

jq reads from stdin when you don’t pass a filename. So any command that prints JSON can feed jq:

  • From a file: cat config.json | jq or jq . config.json
  • From an API: curl -s https://api.example.com/data | jq
  • From another tool: kubectl get pod -o json | jq

Use single quotes around the jq program and around the JSON so the shell doesn’t mangle double quotes and spaces. Double quotes are required inside the JSON itself, so keep them within the single-quoted string (e.g. '{"key":"value"}').


Basic jq usage

Identity: pretty-print

The simplest program is . (a single dot). It means “the whole input” and outputs it, nicely formatted:

echo '{"a":1,"b":2,"c":[3,4,5]}' | jq '.'

Use this when you just want readable JSON.

Field access

Use .key to get a field:

echo '{"name":"Alice","age":30}' | jq '.name'

Output: "Alice"

Nested fields use dot notation:

echo '{"user":{"name":"Alice","role":"admin"}}' | jq '.user.name'

Output: "Alice"

Arrays

  • One element: .[0], .[1], etc.
  • All elements (stream): .[] outputs each element separately.
  • Slice: .[1:3] gives elements from index 1 up to (not including) 3.
echo '["a","b","c","d"]' | jq '.[1:3]'

Output: ["b","c"]

Combining with the pipe

You can chain operations with | inside jq:

echo '{"a":1,"b":2}' | jq '.a'

Output: 1

echo '[{"name":"Alice"},{"name":"Bob"}]' | jq '.[].name'

Output (one per line): "Alice" then "Bob".


Practical examples

Extract one field from an API response

curl -s https://api.github.com/users/octocat | jq '.login'

Or several fields into a new object:

curl -s https://api.github.com/users/octocat | jq '{name: .name, login: .login, id: .id}'

Filter array elements

Keep only items that match a condition with select:

echo '[{"name":"Alice","active":true},{"name":"Bob","active":false}]' | jq '.[] | select(.active)'

Output: {"name":"Alice","active":true}

Build a new array

Transform each element and collect into an array with [ ]:

echo '[{"name":"Alice"},{"name":"Bob"}]' | jq '[.[] | .name]'

Output: ["Alice","Bob"]

Get keys or values

  • Keys: keys returns a list of top-level keys.
  • Values: .[] for an array; for an object, use .[] to stream values or to_entries for key-value pairs.
echo '{"a":1,"b":2}' | jq 'keys'

Output: ["a","b"]


When to reach for jq

Reach for jq when you’re inspecting API responses, pretty-printing or plucking fields out of curl output. It’s the same tool for debugging configs and logs, where you filter and reshape JSON files or log lines, and for scripting, where it sits next to curl, kubectl, or anything else that outputs JSON.

Install it with your package manager (brew install jq, apt install jq, etc.). For the full language (conditionals, functions, modules), see the jq manual.

Once you’re used to echo '{"key":"value"}' | jq, you’ll find yourself piping everything through it.

  • jq
  • json
  • command-line
  • cli
  • shell
  • productivity

Comments