Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over json with jq

Tags:

json

bash

jq

I am parsing an API which sends me a JSON response like this:

{
  "newList": {
    "243": {
      "id": "243",
      "name": "test",
      "create": {
        "date": "2017-08-31 13:57:29"
      }
    },
    "244": {
      "id": "244",
      "name": "test",
      "create": {
        "date": "2017-08-31 13:57:29"
      }
    }
 }
}

I am trying to get the name and the create date out of this using bash with jq, so for with little to no success.

jq '.newList' does work and brings me down one level, but that's not sufficient.

jq '.newList .243' gives me a compile error. Furthermore, the 243 is dynamic and can change at any time. What am I doing wrong here?

like image 385
SnIpY Avatar asked Dec 28 '17 10:12

SnIpY


1 Answers

Assuming your root node name is newList as you have in the question given, to get the id and created date, you can do string interpolation with jq

api-producing-json | jq --raw-output '.newList[] | "\(.id) \(.create.date)"'

This way the filter is independent of the dynamic numbers in the nodes (243, 244). Drop the --raw-output flag if you need the output with quotes.

To process further in a loop, you can iterate it over a bash loop,

while read -r id name date; do
    echo "Do whatever with ${id} ${name} ${date}"
done< <(api-producing-json | jq --raw-output '.newList[] | "\(.id) \(.name) \(.create.date)"')

or to even more carefully delimit the words if you are worried about the spaces in any of the fields, use a delimiter as | in the filter as "\(.id)|\(.name)|\(.create.date)" and use the read command in the while loop by setting IFS=| so the variables are stored appropriately.


Always use the official jq - documentation for help and use this nice playground to test out the filters, jq - online

like image 68
Inian Avatar answered Oct 28 '22 00:10

Inian