Skip to main content

The jq utility for Linux

Use the powerful Linux jq utility to manipulate JSON data, prettify output, and filter nodes directly from your command line and shell scripts.

· 6 min read
View raw
Christophe
Markdown, WSL and Docker lover ~ Insatiable curious.
Cet article existe aussi en français — lire la version française.

Changelog

Latest
added a Docker-first demo to try before installing

The jq utility for Linux

⚡
TL;DR

This article introduces jq, a command-line JSON processor: piping raw API output (using the random-user API as an example) through jq alone pretty-prints it, and adding a filter expression like jq '.results[0].name' extracts just a specific node from the JSON structure.

jq is a powerful utility for Linux that lets you manipulate JSON data from the command line and can be integrated into shell scripts.

The same answer, twice​

By running curl https://randomuser.me/api/ you'll get something like

>user@machine: ~/yourproject
{"results":[{"gender":"female","name":{"title":"Mademoiselle","first":"Milena","last":"Martin"},"location":{"street":{"number":9831,"name":"Rue de L'Abbé-Migne"},"city":"Lengnau (Ag)","state":"Basel-Landschaft","country":"Switzerland","postcode":3789,"coordinates":{"latitude":"-60.0739","longitude":"135.1462"},"timezone":{"offset":"+7:00","description":"Bangkok, Hanoi, Jakarta"}},"email":"milena.martin@example.com","login":{"uuid":"bafdf972-4183-484a-903a-84f2654f0fec","username":"purpleleopard344","password":"cameron","salt":"gGoFrP1a","md5":"af359ca6697c3ac68f4c190583544619","sha1":"19033bc1630d96bba29726823ef91f53800e67d1","sha256":"cac6a35f5135f14707b8b3ec48617f23b4105b1c5e33a2b64597e7a0c7c891a0"},"dob":{"date":"1998-10-10T02:42:04.525Z","age":25},"registered":{"date":"2005-05-01T01:26:36.354Z","age":18},"phone":"079 098 73 86","cell":"077 411 83 18","id":{"name":"AVS","value":"756.9632.2579.59"},"picture":{"large":"https://randomuser.me/api/portraits/women/37.jpg","medium":"https://randomuser.me/api/portraits/med/women/37.jpg","thumbnail":"https://randomuser.me/api/portraits/thumb/women/37.jpg"},"nat":"CH"}],"info":{"seed":"213f93e3e854d33c","results":1,"page":1,"version":"1.4"}}

The JSON is just echoed on the screen, not really readable.

But, as soon as we are redirecting to jq, it'll be better:

>user@machine: ~/yourproject
{
"results": [
{
"gender": "female",
"name": {
"title": "Mademoiselle",
"first": "Salomé",
"last": "Roy"
},
"location": {
"street": {
"number": 2361,
"name": "Rue Dumenge"
},
"city": "Dierikon",
[...]
},
"email": "salome.roy@example.com",
[...]
}
],
"info": {
"seed": "b7ef95d3b252edca",
"results": 1,
"page": 1,
"version": "1.4"
}
}

Same bytes, same API, one extra word on the command line. That already earns jq its place in a pipe, but the reason I really use it is below.

Filtering the output​

Imagine we just need to retrieve the name. To do this, we need to better understand the JSON object.

{
"results": [
{
"gender": "female",
"name": {
"title": "Mademoiselle",
"first": "Salomé",
"last": "Roy"
},
"location": {
[...]
},
[...]
],
[...]
}

The output is a JSON representation having a root property called results. That property is an array. Each element in that array has a name node with a few properties like title, first and last.

If we just want to retrieve the name node, the filter to use with jq is .results[0].name.

>user@machine: ~/yourproject
{
"title": "Ms",
"first": "Brooke",
"last": "Morgan"
}

Learn more about jq filtering.

Seeing It in Action with Docker​

Before installing anything, try both commands from above in a throwaway container. It ships jq and a static snapshot of the randomuser.me response used throughout this article, so the demo works even without network access — though the live API is still reachable if you want to try it for real.

Why Docker first?

The Dockerfile below installs jq and drops a ready-to-use sample.json in the working directory. Nothing to type, download or configure — just pipe it through jq.

Build and run it:

>user@machine: ~/yourproject

Same filter as above, same result, no curl even required. Drop the filter and run cat sample.json | jq alone to see the whole object prettified, or, since the container has network access, try the live version too: curl --silent https://randomuser.me/api/ | jq.

Installing jq​

To verify if jq is already installed on your system, simply run which jq. If you get jq not found as an answer:

Prerequisite: jq

>user@machine: ~/yourproject

Verify:

>user@machine: ~/yourproject

Let's play​

jq can be used without any arguments and in that case, the JSON output will be prettified.

To reproduce the examples above, we'll use a simple JSON free API like https://randomuser.me/api/. If you wish to use another API tool, take a look on https://github.com/public-apis/public-apis#test-data; free ones are those having No in the Auth columns.

randomuser API return every time a new user

On each request, the randomuser API is returning a new object. Don't be surprised if your names differ from mine.

The full prettified answer (click for the details)

Here is the complete object returned by the API, as jq renders it:

{
"results": [
{
"gender": "female",
"name": {
"title": "Mademoiselle",
"first": "Salomé",
"last": "Roy"
},
"location": {
"street": {
"number": 2361,
"name": "Rue Dumenge"
},
"city": "Dierikon",
"state": "Basel-Stadt",
"country": "Switzerland",
"postcode": 5075,
"coordinates": {
"latitude": "-58.3405",
"longitude": "134.0131"
},
"timezone": {
"offset": "+4:30",
"description": "Kabul"
}
},
"email": "salome.roy@example.com",
"login": {
"uuid": "dfda3e32-b8b1-44c9-9aa9-194fc17833d3",
"username": "organiccat614",
"password": "nacked",
"salt": "HRepWJ2P",
"md5": "643f7a890ba9c9fbe04ea971287f57ba",
"sha1": "9407fd8fdf0c344ac1990a89d8d0190f6baabd19",
"sha256": "1317478dbfc61c3feaccea4485a367fb6b195009f15eecd9175f2d1a9215d5df"
},
"dob": {
"date": "1960-05-12T07:27:42.104Z",
"age": 63
},
"registered": {
"date": "2021-05-02T04:18:14.996Z",
"age": 2
},
"phone": "077 228 21 12",
"cell": "078 051 38 48",
"id": {
"name": "AVS",
"value": "756.1071.1525.27"
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/74.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/74.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/74.jpg"
},
"nat": "CH"
}
],
"info": {
"seed": "b7ef95d3b252edca",
"results": 1,
"page": 1,
"version": "1.4"
}
}

Conclusion​

Two things to remember: jq alone makes any JSON readable, and jq '.some.path' extracts exactly the node you need — which is what turns an API answer into something a shell script can consume.

jq quickly becomes a reflex: I use it in Troubleshooting for Docker containers to read docker inspect output, and in building a blog post analyzer with Ollama to format the local LLM's JSON responses, for instance.

And on the days when the filter you need — a group_by, a select on a date — just won't come back to you, ai-data asks a local LLM for five jq commands tailored to your own file, and drops the one you pick at your prompt, ready to read before you run it.

For the times when the console is not the right tool for JSON, this blog has three more: Rendering a JSON file as a mind map, JSON - Online linter and JSON - Faker & Mockup.


Was this article helpful?
Did you try the steps in this article?