Home About

Published

- 4 min read

How to Query JSON by Using jq in Bash

bash json
img of How to Query JSON by Using jq in Bash

Updated on: 7th October 2022 - Added more examples.

JSON stands for JavaScript Object Notation. Many web API’s today returns a JSON response when you communicate with the API endpoint.

For those that are not familiar with JSON, it looks something like this:

   [
    {
        "firstName": "bob",
        "lastName": "smith",
        "gender": "male"
    },
    {
        "firstName": "jenny",
        "lastName": "lee",
        "gender": "female"
    },
    {
        "firstName": "andy",
        "lastName": "king",
        "gender": "male"
    },
    {
        "firstName": "stella",
        "lastName": "le",
        "gender": "female"
    }
]

In short, the square brackets ”[ ]” represents a list and the curly braces "" represents each object in the list.

Example using jq to count the number of males and females.

   $ cat names.json | jq -r '.[].gender' | sort | uniq -c
      2 female
      2 male

What is jq and why I use it?

jq is a popular lightweight utility for querying JSON. It is often used in Bash when you “curl” against a web API and it returns a JSON response in which you need to query.

I use jq because I don’t always want to rely on Python to handle basic queries to a web API. Especially when it is used within a CI/CD pipeline that is running on Linux (bash)

Here is one other example how I use jq to query the Kubernetes cluster API to extract all the pod names.

   $ curl -s http://127.0.0.1:8001/api/v1/pods | jq -r '.items[].metadata.name' | sort
calico-kube-controllers-f7868dd95-xx
calico-node-xx
coredns-7f9c69c78c-xx
dashboard-metrics-scraper-78d7698477-xx
hostpath-provisioner-5c65fbdb4f-xx
kubernetes-dashboard-85fd7f45cb-xx
lets-encrypt-cron-27282960-xx
lets-encrypt-cron-27282960-xx
lets-encrypt-cron-27293040-xx
lets-encrypt-cron-27293040-xx
lets-encrypt-cron-27303120-xx
lets-encrypt-cron-27303120-xx
metrics-server-8bbfb4bdb-xx
mysql-wordpress-5d69547997-xx
mysql-wordpress-6875c877f6-xx
nfs-subdir-external-provisioner-565c9fbd4c-xx
nginx-ingress-microk8s-controller-xx
wordpress-65fb8bb76d-xx
wordpress-7b7bbfc5dc-xx
wordpress-7b7bbfc5dc-xx

How to Query using jq

In this section, I will demonstrate jq by using the following requirements. I will be querying the names.json file as shown in the introduction.

  • Show the first object in the list
  • Show first names and genders only
  • Show the object where firstName is andy
  • Show objects where lastName starts with “le”
  • Replace a value in JSON
  • Compressing result into a single line

Show the first object in the list

A list always begins with index 0, so the following will get the first object in the list.

   $ cat names.json | jq '.[0]'
{
  "firstName": "bob",
  "lastName": "smith",
  "gender": "male"
}

Show first names and genders only

Use the jq pipe to filter only the fields we want to return.

   # Note: When we don't specify the index, it will use all the objects in the list.
$ cat names.json | jq  '.[] | {firstName,gender}'
{
  "firstName": "bob",
  "gender": "male"
}
{
  "firstName": "jenny",
  "gender": "female"
}
{
  "firstName": "andy",
  "gender": "male"
}
{
  "firstName": "stella",
  "gender": "female"
}

Show the object where firstName is andy

Use the select function to specify the condition to check

   # Note: When we don't specify the index, it will use all the objects in the list.
$ cat names.json | jq  '.[] | select(.firstName == "andy")'
{
  "firstName": "andy",
  "lastName": "king",
  "gender": "male"
}

Show objects where lastName starts with “le”

   # Note: When we don't specify the index, it will use all the objects in the list.
$ cat names.json | jq  '.[] | select(.lastName | startswith("le"))'
{
  "firstName": "jenny",
  "lastName": "lee",
  "gender": "female"
}
{
  "firstName": "stella",
  "lastName": "le",
  "gender": "female"
}

Replace value in JSON

Changing the lastName from “king” to “wong”

   # Note: When we don't specify the index, it will use all the objects in the list.
$ cat names.json | jq '.[] | select(.firstName == "andy") | .lastName = "wong"'
{
  "firstName": "andy",
  "lastName": "wong",
  "gender": "male"
}

Compressing result into a single line

Putting the result into a single line can be very useful, especially when passing the result into another API call via cURL for example.

   # Note: When we don't specify the index, it will use all the objects in the list.
$ RESULT=$(cat names.json | jq '.[] | select(.firstName == "andy")' -c)
$ echo $RESULT
{"firstName":"andy","lastName":"king","gender":"male"}

Conclusion

jq is very powerful especially when it is used in a CI/CD pipeline.

If you would like to see more examples or questions on jq, please leave a comment below.

Otherwise you can take a look at the jq documentation here.