JQ How to replace entire array with a variable arg
Asked Answered
E

1

6

So I can do this

jq --arg title "Test" 'select(.title == $title) | .alert.notifications = [{"uid":"foo"},{"uid":"bar"}]' json

Which outputs the desired results:

{
  "alert": {
    "notifications": [
      { 
        "uid": "foo" 
      },
      { 
        "uid": "bar" 
      }
    ]
  },
  "title": "Test"
}

However, I need to put the array in a var and supply it on the fly instead, like:

array='{ "uid": "foo" },{ "uid": "bar"}'

jq -r --arg title "$t" --arg array "$array" 'select(.title == $title) | .alert.notifications = [$array]'

But that results in this undesired output

{
  "alert": {
    "notifications": [
      "{ \"uid\": \"foo\" },{ \"uid\": \"bar\" }"
    ]
  },
  "title": "Test"
}

Any way to get around this? Much appreciated!!

Eveleen answered 17/3, 2022 at 5:26 Comment(0)
I
5

Use --argjson (instead of --arg) for JSON input. Note, however, that {"uid": "foo" }, {"uid": "bar"} by itself is not (yet) valid JSON. You need to wrap it into brackets to make it an array (otherwise, jq will (rightfully) complain about a superfluous comma between the two objects).

Brackets added to the string provided for --argjson:

array='{"uid": "foo" }, {"uid": "bar"}'

jq --arg title "$t" --argjson array "[$array]" \
  'select(.title == $title) | .alert.notifications = $array'

Brackets added to the shell variable called array:

array='[{"uid": "foo" }, {"uid": "bar"}]'

jq --arg title "$t" --argjson array "$array" \
  'select(.title == $title) | .alert.notifications = $array'

Also note that if your output is JSON, you don't need the -r option.

{
  "alert": {
    "notifications": [
      {
        "uid": "foo"
      },
      {
        "uid": "bar"
      }
    ]
  },
  "title": "Test"
}

If you don't have the option to use --argjson instead of --arg (because, for example, the input may or may not be JSON and you can only test it after populating the variables), you can use the fromjson builtin to convert a JSON-encoded string into actual JSON (said "testing" is not included in these examples).

Brackets added inline just before applying fromjson:

array='{"uid": "foo" }, {"uid": "bar"}'

jq --arg title "$t" --arg array "$array" \
  'select(.title == $title) | .alert.notifications = ("[\($array)]" | fromjson)'

Brackets added to the string provided for --arg:

array='{"uid": "foo" }, {"uid": "bar"}'

jq --arg title "$t" --arg array "[$array]" \
  'select(.title == $title) | .alert.notifications = ($array | fromjson)'

Brackets added to the shell variable called array:

array='[{"uid": "foo" }, {"uid": "bar"}]'

jq --arg title "$t" --arg array "$array" \
  'select(.title == $title) | .alert.notifications = ($array | fromjson)'
Isolde answered 17/3, 2022 at 5:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.