Home > OS >  jq: insert{"key": "value"} pair in the nested structure
jq: insert{"key": "value"} pair in the nested structure

Time:02-15

I just wonder how we can achieve this with simple online jq.

AS_IS

{
  "rules": {
    "aaa": {
      "xxx": {
        "url": "https://microsoft.com"
      },
      "xxxx": {
        "url": "https://netflix.com"
      }
    },
    "bbb": {
      "xxx": {
        "url": "https://amazon.com"
      }
    },
    "ccc": {
      "xxx": {
        "url": "https://google.com"
      }
    }
  }
}

TO_BE

{
  "rules": {
    "aaa": {
      "xxx": {
        "url": "https://microsoft.com"
      },
      "xxxx": {
        "url": "https://netflix.com"
      }
    },
    "bbb": {
      "xxx": {
        "url": "https://amazon.com"
      }
    },
    "ccc": {
      "xxx": {
        "url": "https://google.com",
        "pass": "abc"
      }
    }
  }
}

What I tried so far is

.rules[] | select(.xxx.url | try contains("google.com")) | .xxx  = {"pass": "abc"}

and the output is below, and I successfully insert "pass": "abc".

{
  "xxx": {
    "url": "https://google.com",
    "pass": "abc"
  }
}

but I want to get the whole lines of code. (Not a part of it) ref. https://jqplay.org/s/S_UWrrLRl5

CodePudding user response:

The idea is right, but ensure the last update happens without traversing down to the leaf path (at the same level as xxx), but relative to the root path by simply wrapping the filter under (..)

( .rules[] | select(.xxx.url | try contains("google.com")) | .xxx )  = {"pass": "abc"}

Always prefer using exact match conditions instead of a partial match

( .rules[] | select(.xxx.url == "https://google.com") | .xxx )  = {"pass": "abc"}

CodePudding user response:

Why not just:

.rules.ccc.xxx.pass = "abc"

or more dynamically:

walk(if type=="object" 
        and (.url|type)=="string" 
        and (.url|endswith("google.com")) 
     then .pass = "abc" else . end)
  • Related