user766353
user766353

Reputation: 537

Why does jq expression loop through array separately from another similar expression at the same level?

I have a JSON file that looks like the following:

{
    "people": {
        "company": "Acme",
        "department": "Dev",
        "perks": {
            "eat": "pizza",
            "drink": "beer",
            "play": "twister"
        },
        "names": [{
                "last_name": "Smith",
                "first_names": [{
                        "name": "Bill",
                        "nickname": "Billy"
                    },
                    {
                        "name": "Alice",
                        "nickname": "Al"
                    },
                    {
                        "name": "Mary",
                        "nickname": "Mare"
                    }
                ]
            },
            {
                "last_name": "Brown",
                "first_names": [{
                        "name": "Gil",
                        "nickname": "Gillie"
                    },
                    {
                        "name": "Bob",
                        "nickname": "Bobby"
                    },
                    {
                        "name": "Mary",
                        "nickname": "Big M"
                    }
                ]
            },
            {
                "last_name": "Sanchez",
                "first_names": [{
                        "name": "Gil",
                        "nickname": "Gilster"
                    },
                    {
                        "name": "Jose",
                        "nickname": "Jo"
                    },
                    {
                        "name": "Marlena",
                        "nickname": "Marly"
                    }
                ]
            }
        ]
    }
}

I'm looking for output that looks like the following:

Acme
Dev
beer
Smith, Bill, Billy
Smith, Alice, Al
Smith, Mary, Mare
Brown, Gil, Gillie
Brown, Bob, Bobby
Brown, Mary, Big M
Sanchez, Gil, Gilster
Sanchez, Jose, Jo
Sanchez, Marlena, Marly

I'm using this query:

$ jq -r '.people | .company, .department, .perks.drink, (.names[] | "\(.last_name), \(.first_names[].name), \(.first_names[].nickname)")'

and get this output, obviously wrong:

Acme
Dev
beer
Smith, Bill, Billy
Smith, Alice, Billy
Smith, Mary, Billy
Smith, Bill, Al
Smith, Alice, Al
Smith, Mary, Al
Smith, Bill, Mare
Smith, Alice, Mare
Smith, Mary, Mare
Brown, Gil, Gillie
Brown, Bob, Gillie
Brown, Mary, Gillie
Brown, Gil, Bobby
Brown, Bob, Bobby
Brown, Mary, Bobby
Brown, Gil, Big M
Brown, Bob, Big M
Brown, Mary, Big M
Sanchez, Gil, Gilster
Sanchez, Jose, Gilster
Sanchez, Marlena, Gilster
Sanchez, Gil, Jo
Sanchez, Jose, Jo
Sanchez, Marlena, Jo
Sanchez, Gil, Marly
Sanchez, Jose, Marly
Sanchez, Marlena, Marly

It seems that .first_names[].nickname is being looped over for each entry of .first_names[].name, producing the output seen, but I don't see why.

Upvotes: 1

Views: 190

Answers (1)

hobbs
hobbs

Reputation: 240531

Well, that's a case of "how is it supposed to know that's what you wanted?". Whenever a \() interpolation expression returns multiple items, jq will duplicate the output string with each item interpolated. If several interpolations each do that, then they multiply. It doesn't know that you wanted parallel iteration instead.

You can write what you want explicitly:

jq -r '.people | 
  .company, .department, .perks.drink, 
  (.names[] | .last_name as $last |
    .first_names[] |
    "\($last), \(.name), \(.nickname)"
  )'

Upvotes: 4

Related Questions