Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing nested json with jq

Tags:

json

jq

I am parsing a nested json to get specific values from the json response. The json response is as follows:

{ 
"custom_classes": 2,
"images": 
    [ 
      { 
        "classifiers": 
        [ 
          { 
            "classes": 
            [ 
              { 
                "class": "football",
                "score": 0.867376 
              } 
            ], 
            "classifier_id": "players_367677167",
            "name": "players" 
          } 
        ], 
        "image": "1496A400EDC351FD.jpg" 
      } 
    ], 
"images_processed": 1 
}

From the class images=>classifiers=>classes:"class" & "score" are the values that I want to save in a csv file. I have found how to save the result in a csv file. But I am unable to parse the images alone. I can get custom_classes and image_processed.

I am using jq-1.5.

The different commands I have tried :

curl "Some address"| jq '.["images"]'
curl "Some address"| jq '.[.images]'
curl "Some address"| jq '.[.images["image"]]'

Most of the times the error is about not being able to index the array images.

Any hints?

like image 481
Vini Avatar asked Dec 14 '22 20:12

Vini


2 Answers

I must say, I'm not terribly good at jq, so probably all those array iterations could be shorthanded somehow, but this yields the values you mentioned:

cat foo.json | jq ".[] | .images | .[] | .classifiers | .[] | .classes | .[] | .[]"

If you want the keys, too, just omit that last .[].`

Edit As @chepner pointed out in the comments, this can indeed be shortened to

cat foo.json | jq ".images[].classifiers[].classes[] | [.class, .score] | @csv "
like image 158
Oliver Baumann Avatar answered Dec 16 '22 09:12

Oliver Baumann


Depending on the data this filter which uses Recursive Descent: .., objects and has may work:

.. | objects | select(has("class")) | [.class,.score] | @csv

Sample Run (assuming data in data.json)

$ jq -Mr '.. | objects | select(has("class")) | [.class,.score] | @csv' data.json
"football",0.867376

Try it online at jqplay.org

Here is another variation which uses paths and getpath

getpath( paths(has("class")?) ) | [.class,.score] | @csv

Try it online at jqplay.org

like image 42
jq170727 Avatar answered Dec 16 '22 08:12

jq170727