jq is a command line tool for working with JSON. Like JSON, jq is ubiquitous, as it comes installed in most Linux distributions, and you would have at least used it to pretty print a JSON file or response:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq
But jq can do more. Much more. jq is on every “five command line tools to learn as a developer” video on YouTube. The Primagen even calls it the BEST CLI tool.
Using jq has been the one of the most useful things I have done in a long time.
In this interactive guide, I will show how you can use jq to do everything from pretty printing JSON to transforming JSON using filters like:
curl 'https://jsonplaceholder.typicode.com/users' | jq \
'.[] | select(.address.city == "South Christy") | {name, username, email}'
Or go to the jq Playground instead.
Install jq
This guide lets you to edit and run jq filters directly in your browser. However, if you’d like to follow along on your machine, you can instead install jq.
jq is available on most package managers. You can also download the binary directly or build it from source.
To verify the installation, run:
jq --help
Basic Filters
Identity Filter
The most basic filter in jq is the identity filter .
, which represents the current JSON object. It’s the default filter in jq and returns the input JSON unchanged:
echo '{"id": 1,"name":"Leanne Graham","website":"hildegard.org"}' | jq '.'
Notice how jq pretty prints the JSON.
Tip: You can edit these commands. Try editing the above command to see the output without the jq filter.
jq can also apply filters directly to a file (user.json
):
{
"id": 1,
"name": "Leanne Graham",
"website": "hildegard.org"
}
jq '.' user.json
Another common usage is to pipe JSON responses from curl
commands to jq:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq '.'
Access Specific Fields
You can access specific fields from JSON objects using the object index filter. Try editing the filter below to access different fields from the JSON object:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq '.name'
Access Nested Fields
Similarly, you can also access nested fields:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq '.address.zipcode'
Try accessing the latitude (lat
) from the object.
Filter JSON Arrays
JSON arrays commonly represent a list of objects. To access an object at a specific index, use the array index filter:
curl 'https://jsonplaceholder.typicode.com/users' | jq '.[0]'
The above example gets the first object from the array. Try changing the index to get the other objects.
Note: Similar to most programming languages, array indexes start at 0 in jq.
Slice JSON Arrays
You can also slice an array into a subarray. For example, you can get the objects from index 3 to 6 (excluding) in a subarray using the array slice filter:
curl 'https://jsonplaceholder.typicode.com/users' | jq '.[3:6]'
Tip: You can specify only the start or end of a slice:
curl 'https://jsonplaceholder.typicode.com/users' | jq '.[:4]'
You can also specify a negative index to select from the end:
curl 'https://jsonplaceholder.typicode.com/users' | jq '.[-6:-3]'
Iterate JSON Arrays
Instead of accessing a single object or a slice from the array, you can use the array value iterator filter to iterate over the entire array. For example, to list the details of all users:
curl 'https://jsonplaceholder.typicode.com/users' | jq '.[]'
This is useful when you, say, want to get just the names of all users:
curl 'https://jsonplaceholder.typicode.com/users' | jq '.[].name'
Tip: The
-r
flag outputs raw strings without quotes.
Construct Objects and Arrays
You can also create JSON objects and arrays with custom fields. This is useful when you only care about specific fields and want to omit others.
Construct New JSON Objects
For example, if you only want the name, email, and company of a user, you can construct a new object using {}
with only those fields:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq \
'{"name": .name, "email": .email, "company": .company.name}'
Notice how we created a new emailAddress
property.
Construct New JSON Arrays
Similarly, you can construct a new array of objects using []
:
curl 'https://jsonplaceholder.typicode.com/users' | jq \
'[.[] | {"name": .name, "emailAddress": .email, "company": .company.name}]'
But what’s |
?
Combine Filters
The pipe operator |
feeds the left filter’s output to the right filter’s input. In the last example, we first use the filter .[]
to get the array, and then the filter {"name": .name, "emailAddress": .email, "company": .company.name}
to construct a new array.
We have also been combining filters from the beginning. For example, when we access nested fields like this:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq '.address.zipcode'
We are actually combining two filters:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq '.address | .zipcode'
Use Functions
jq comes built-in with handy functions that can do a lot of different things.
Get Length
The length function returns the length of a value:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq '.name | length'
The below example gets the length of each comment in a post:
curl 'https://jsonplaceholder.typicode.com/posts/1/comments' | jq \
'.[].body | length'
Get Keys
Another useful function is the keys function. As you might have already guessed, it returns the keys of an object in an array:
curl 'https://jsonplaceholder.typicode.com/users/1' | jq '. | keys'
Notice how the keys are sorted alphabetically in the output. You can use the keys_unsorted function instead to preserve the order.
Map Filters
The map function map(f)
applies the filter f
to each value of an input array or object. The example below shows how a filter is mapped to the entire array of objects:
curl 'https://jsonplaceholder.typicode.com/users' | jq \
'map({name: .name, city: .address.city})'
Here’s a better example using a more helpful map. This map will create a “slug” from a user’s name and their city:
curl 'https://jsonplaceholder.typicode.com/users' | jq \
'.[:3] |
map({name: .name, city: .address.city, slug: ((.name + "-" + .address.city |
gsub(" "; "-") |
ascii_downcase))})'
The gsub function is a built-in function that’s used for substitutions. Here, we replace empty spaces with -
in the slug. The ascii_downcase function then converts the slug to lowercase/downcase.
jq has even more built-in functions that cover a wider array of use cases. I will leave it up to you to explore.
Select Values
The select function is, by a mile, the most useful feature in jq, at least for me. It does what it says: select based on the values of fields.
For example, you can select only the users whose city is “South Christy”:
curl 'https://jsonplaceholder.typicode.com/users' | jq \
'.[] | select(.address.city == "South Christy") | {name, username, email}'
The output shows only a single user whose city is “South Christy.” Try using the select function on other JSON.
Transform JSON
In this interactive tutorial, we incrementally built our JSON wrangling skills using jq. Like all command line tools, you build up your skills with practice. You will progressively improve and become a better developer with jq in your arsenal.
So far, we have only managed to scratch the surface of what’s capable with jq. But the part we scratched is a good foundation to learn more and do stuff like:
curl 'https://jsonplaceholder.typicode.com/users' | jq \
'group_by(.address.city) |
map({
city: .[0].address.city,
user_count: length,
users: [.[] | {
name: .name,
username: .username,
slug: (.username + "-" + (.address.city))
}]
})'
The utility of jq scales with the size of the JSON. There’s nothing like typing a one-liner that gets you the data you want from a 10000-line JSON:
curl 'https://api.github.com/repos/apache/apisix/contributors?per_page=100' | jq \
'sort_by(.contributions) |
reverse |
map({username: .login, contributions}) |
.[0:5]'
You can go further and work with your own examples in the jq Playground.
Thank you for reading "An Interactive Guide to Transforming JSON with jq."
Subscribe via email or RSS feed to be the first to receive my content.
If you liked this post, check out my featured posts or learn more about me.