How to properly chain multiple jq statements together when processing json in the shell such as with curl?
Asked Answered
W

2

7

I am new to jq so if this is not a jq question or a json question please point me in the right direction. I am not sure of the correct terminology so it is making it hard for me to properly articulate the problem.

I am using to curl to pull some json that I want to filter out keys with specific values. Here is some of the sample json:

{
  "id": "593f468c81aaa30001960e16",
  "name": "Name 1",
  "channels": [
    "593f38398481bc00019632e5"
  ],
  "geofenceProfileId": null
}
{
  "id": "58e464585180ac000a748b57",
  "name": "Name 2",
  "channels": [
    "58b480097f04f20007f3cdca",
    "580ea26616de060006000001"
  ],
  "geofenceProfileId": null
}
{
  "id": "58b4d6db7f04f20007f3cdd2",
  "name": "Name 3",
  "channels": [
    "58b8a25cf9f6e19cf671872f"
  ],
  "geofenceProfileId": "57f53018271c810006000001"
}

When I run the following command:

curl -X GET -H 'authorization: Basic somestring=' "https://myserver/myjson" |
  jq '.[] | {id: .id, name: .name, channels: .channels, geofenceProfileId: .geofenceProfileId}' |
  jq '.[] | select(.channels == 58b8a25cf9f6e19cf671872f)'

I get the following error:

jq: error: syntax error, unexpected IDENT, expecting ';' or ')' (Unix shell quoting issues?) at , line 1: .[] | select(.channels == 58b8a25cf9f6e19cf671872f)
jq: 1 compile error % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 351k 0 351k 0 0 1109k 0 --:--:-- --:--:-- --:--:-- 1110k

Is this error because jq pretty prints the output of the first statement and the second statement is expecting it to be in one code block? If so, how do I convert it back to non pretty print format or how can I use jq to run a new filter on the output?

Basically I am trying to parse hundreds of records and filter out all of the records that are in a specific channel number or have a specific geofenceProfileId.

Waters answered 11/11, 2017 at 4:21 Comment(0)
F
9

I'd suggest you start with:

jq 'select(.channels | index("58b8a25cf9f6e19cf671872f"))'

In fact, this might even be exactly the filter you want. If you want to remove the "channels" once you've made the selection, you could augment the filter above as follows:

select(.channels | index("58b8a25cf9f6e19cf671872f")) | del(.channels)

The main thing to note is that one can create a pipeline WITHIN a single invocation of jq. So most likely you'll end up with: curl ... | jq ...

Btw

The jq expression {"id": .id} can be abbreviated to {id}, so instead of:

{id.id, name: .name, channels: .channels, geofenceProfileId: .geofenceProfileId}

you could write:

{id, name, channels, geofenceProfileId}
Forequarter answered 11/11, 2017 at 5:22 Comment(1)
Thank you so much. The nesting of statements is tricky to get the handle of. I spent hours trying to figure out what I was doing wrong and that is exactly what I was looking for!Waters
T
0

Probably not related to your case but I managed to transform my command

npm pkg get version -ws | jq "select(to_entries | min_by(.value) | .value)"

to

npm pkg get version -ws | jq "to_entries | min_by(.value) | .value"

and result is same. May be it helps. SO the idea is to pipe inside jq statement

Teece answered 31/8, 2022 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.