Nick Hatfield
Nick Hatfield

Reputation: 385

JQ How to update selected objects while also printing out the entire JSON document

I'm trying to simply update an array, while also printing out the full JSON body. Whenever I update the array, I can only output the JSON object that Im updating rather than printing the entire JSON document, plus the updates.

Command:

array='{"uid": "foo123" }, {"uid": "bar123"}'
t=Test

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

Input:

{
  "data": [
    {
      "alert": {
        "notifications": [
          {
            "uid": "foo"
          },
          {
            "uid": "bar"
          }
        ]
      },
      "title": "Test"
    },
    {
      "alert": {
        "notifications": [
          {
            "uid": "foo1"
          },
          {
            "uid": "bar1"
          }
        ]
      },
      "title": "Test2"
    }
  ]
}

Undesired Output:

{
  "data": [
    {
      "alert": {
        "notifications": [
          {
            "uid": "foo"
          },
          {
            "uid": "bar"
          }
        ]
      },
      "title": "Test"
    },
    {
      "alert": {
        "notifications": [
          {
            "uid": "foo1"
          },
          {
            "uid": "bar1"
          }
        ]
      },
      "title": "Test2"
    }
  ],
  "alert": {
    "notifications": [
      {
        "uid": "foo123"
      },
      {
        "uid": "bar123"
      }
    ]
  }
}

Desired Output:

{
  "data": [
    {
      "alert": {
        "notifications": [
          {
            "uid": "foo123"
          },
          {
            "uid": "bar123"
          }
        ]
      },
      "title": "Test"
    },
    {
      "alert": {
        "notifications": [
          {
            "uid": "foo1"
          },
          {
            "uid": "bar1"
          }
        ]
      },
      "title": "Test2"
    }
  ]
}

I have tried a few different scenarios and it the closest I have come is the undesired output. Any help would be greatly appreciated!

Thanks,

Upvotes: 1

Views: 535

Answers (1)

pmf
pmf

Reputation: 36141

Try updating |= the data field with a map:

array='{"uid": "foo123" }, {"uid": "bar123"}'
t=Test

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

Alternatively, wrap the LHS of the assigment into parentheses to retain the context:

array='{"uid": "foo123" }, {"uid": "bar123"}'
t=Test

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

In any case, there's no need for .|.

Upvotes: 2

Related Questions