'JQ map objects to array

I have this input data:

[
  {
    "attributes": {
      "created": "2021-10-18T12:02:39+00:00",
      "enabled": true,
      "expires": null,
      "notBefore": null
    },
    "contentType": null,
    "id": "https://kjkljk./secrets/-/1",
    "managed": null,
    "name": "pw",
    "tags": {}
  },
  {
    "attributes": {
      "created": "2021-10-18T12:06:16+00:00",
      "enabled": true,
      "expires": null,
      "notBefore": null
    },
    "contentType": "",
    "id": "https://kjklj./secrets/-/2",
    "managed": null,
    "name": "pw",
    "tags": {}
  }
]

I need to use jq to extract the id values into a new array where enabled is set to true. this is what I have so far:

.[] | select(any(.attributes; .enabled== true)) | {id} 

but it only results in this:

{
  "id": "https://kjkljk./secrets/-/1"
}
{
  "id": "https://kjklj./secrets/-/2"
}

how can i make these two objects into an array of strings instead?

[
  "id": "https://kjkljk./secrets/-/1",
  "id": "https://kjklj./secrets/-/2"
]


Solution 1:[1]

Use map instead of .[] to retain the array:

map(select(any(.attributes; .enabled)) | {id})
[
  {"id": "https://kjkljk./secrets/-/1"},
  {"id": "https://kjklj./secrets/-/2"}
]

Demo

Note that this produces an array of objects [{…},{…}], what I believe is what you asked for although in your desired output you are missing the curly object braces { }. To make an "array of strigs" instead, use .id instead of {id} like so

map(select(any(.attributes; .enabled)) | .id)
[
  "https://kjkljk./secrets/-/1",
  "https://kjklj./secrets/-/2"
]

Demo

(Also, you can use .enabled instead of .enabled == true)

Solution 2:[2]

Something like:

$ jq '[.[] | select(.attributes.enabled) | .id]' input.json
[
  "https://kjkljk./secrets/-/1",
  "https://kjklj./secrets/-/2"
]

Solution 3:[3]

This should work:

map(select(any(.attributes; .enabled == true)) | .id)

Explanation: Rather than splitting the array with .[], the map() function leaves the array structure intact but operates on the elements. Using .id rather than {id} avoids creating a dictionary for each selected value.

If I understand right, you could also replace any(.attributes; .enabled == true) with just .attributes.enabled == true.

Solution 4:[4]

Like already written in the answers, comments before, your wished output is not valid json.

So you have to options. I pasted your input file in SO-70302009.json

  1. Wrap the id line as objects jq 'map({id: select(any(.attributes; .enabled)) | .id})' "./SO-70302009.json" to get
[
  {
    "id": "https://kjkljk./secrets/-/1"
  },
  {
    "id": "https://kjklj./secrets/-/2"
  }
]
  1. Make an array of ids jq '{ ids: map(select(any(.attributes; .enabled)) | .id) }' "./SO-70302009.json" to get
{
  "ids": [
    "https://kjkljk./secrets/-/1",
    "https://kjklj./secrets/-/2"
  ]
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 pmf
Solution 2 Shawn
Solution 3 Gordon Davisson
Solution 4 KargWare