msmithwr
msmithwr

Reputation: 51

Having trouble searching and replacing in my JSON using jq

I have been looking at trying to get this to work for a number of days but I am stuck.

I have a json data structure with values in it that I want to update, essentially using my json as a database to store configuration values. Here is my JSON:

{
  "Actions": [
    {
      "Number": 1012,
      "RollbackPoint": "xxx_1012_RollbackPoint_xxx",
      "Parameters": [
        {
          "Name": "accountType",
          "Value": "xxx_1012_accountType_xxx"
        },
        {
          "Name": "userPassword",
          "Value": "xxx_1012_userPassword_xxx"
        }
      ]
    },
    {
      "Number": 1015,
      "RollbackPoint": "xxx_1015_RollbackPoint_xxx",
      "Parameters": [
        {
          "Name": "accountType",
          "Value": "xxx_1015_accountType_xxx"
        },
        {
          "Name": "skipExport",
          "Value": "xxx_1015_skipExport_xxx"
        }
      ]
    }
  ]
}

I want to perform two updates

  1. Update RollbackPoint to "1012" where Number = 1015
  2. Update value to "AWS" where name = "accountType" under Parameters, where Number = 1012

So far the closest I have got to is using this:

cat json.txt | jq  '.[] | map(. + {RollbackPoint:(if (."Number") == 1015 then "1015" else .RollbackPoint end)})'

But this strips off the Actions[] element so its no good for me, I don't know where to even start on update 2...

Any help would be greatly appreciated, over 5 hours on google and I am still nowhere near.

Many thanks Matt

Upvotes: 5

Views: 851

Answers (2)

jq170727
jq170727

Reputation: 14645

Here is another jq solution

 .Actions[] |= (
      if .Number == 1015 then .RollbackPoint = "1012" else . end
    | if .Number == 1012 then .Parameters[] |= (
         if .Name == "accountType" then .Value = "AWS" else . end
      ) else . end
 )

Upvotes: 0

Jeff Mercado
Jeff Mercado

Reputation: 134811

You can make use of the // operator to mimic (IMHO) nicer if-else trees in conjunction with various filtering filters. Makes it rather easy to follow, compared to a large if-else tree.

.Actions |= map(
    (select(.Number == 1015) |
        .RollbackPoint = "1012"
    ) //
    (select(.Number == 1012) |
        .Parameters |= map((select(.Name == "accountType") | .Value = "AWS") // .)
    ) //
    .
)

Upvotes: 8

Related Questions