5

I want to conditionally update an element value based on the value of another element within the same array.

For example, I want to find name=="weather" and change checked from "true" to "false"

[
  {
    "originalSourceId": null,
    "sourceConnection": {
      "id": null,
      "version": null,
      "properties": [
        {
          "id": null,
          "version": null
        }
      ],
      "name": "POSTGRESQL",
      "businessName": null
    },
    "checked": true,
    "newlyAdded": false,
    "discoveredEntities": [
      {
        "name": "weather",
        "checked": true,
        "checkedBeforeEdit": false,
        "storeFieldsAsStrings": false
      },
      {
        "name": "weather_2",
        "checked": true,
        "checkedBeforeEdit": false,
        "storeFieldsAsStrings": false
      }
    ],
    "defaultLevel": "MANAGED"
  }
]

the checked element will update to "false" for the same object with name = "weather"

[
  {
    "originalSourceId": null,
    "sourceConnection": {
      "id": null,
      "version": null,
      "properties": [
        {
          "id": null,
          "version": null
        }
      ],
      "name": "POSTGRESQL",
      "businessName": null
    },
    "checked": true,
    "newlyAdded": false,
    "discoveredEntities": [
      {
        "name": "weather",
        "checked": false,
        "checkedBeforeEdit": false,
        "storeFieldsAsStrings": false
      },
      {
        "name": "weather_2",
        "checked": true,
        "checkedBeforeEdit": false,
        "storeFieldsAsStrings": false
      }
    ],
    "defaultLevel": "MANAGED"
  }
]
peak
  • 105,803
  • 17
  • 152
  • 177
CLO
  • 103
  • 8
  • I've tried jq . | jq '[.[].discoveredEntities[] | if (.name=="weather") then (.checked = "false") else . end]' ./test.json. But it is only return portion of it back with updated checked = false for weather. [ { "name": "weather", "checked": "false", "checkedBeforeEdit": false, "storeFieldsAsStrings": false }, { "name": "weather_2", "checked": true, "checkedBeforeEdit": false, "storeFieldsAsStrings": false } ] – CLO Sep 04 '18 at 18:13

3 Answers3

4

Figured it out.

jq '[.[].discoveredEntities[] |= if (.name=="weather") then (.checked = "false") else . end]'\
    ./test.json
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
CLO
  • 103
  • 8
  • 1
    You don't need the outer square brackets `[]`, in this context, you're putting the results in an array. But since the body is just assignments, the initial input will always be returned. You'll end up with your original input updated, but in an array. – Jeff Mercado Sep 05 '18 at 06:20
  • 1
    It would be more consistent with the remainder of the document to use the boolean value `false` rather than the string `"false"`. – peak Sep 07 '18 at 18:04
3

For these sorts of updates, it's easier to visualize if you think of it this way, locate the items you want to update first, then update them.

 (.[].discoveredEntities[] | select(.name == "weather").checked) = false
#[ locate the items to update                         ]
#                                                      [ update them   ]
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
  • While the update works, it has an unintended side effect of returning filtered results. Is there any way to include unmodified items to the result set? – Sergii Shymko Nov 17 '22 at 05:03
0

Using map here yields a very straightforward if somewhat pedestrian solution:

map( .discoveredEntities |=
        map(if .name == "weather" then .checked = false else . end))

Note that it is evidently more appropriate to use false here rather than "false".

peak
  • 105,803
  • 17
  • 152
  • 177