Home > Enterprise >  JQ - Deep child replace through wildcard search, but check parent presence with merge to the origina
JQ - Deep child replace through wildcard search, but check parent presence with merge to the origina

Time:04-14

This is a kind of extension to my previous question JQ - Deep child value replace through wildcard search and merge to the original JSON

I want to check the presence of a particular key in some parents before replacing the child. Loosely, translated to CSS selector, I want something like * > fixedKeyCheckPresence > * > fixedKeyCheckValue

Input:

{
  "randomKey1": {
    "randomKey2": [
      {
        "randomKeyUnderAnyLevel11": {
          "fixedKeyCheckPresence": {
            "randomeKeyUnderAnyLevel23": {
              "fixedKeyCheckValue": "Foo"
            }
          }
        }
      }
    ]
  },
  "randomKey11": {
    "fixedKeyCheckPresence": {
      "randomeKeyUnderAnyLevel123": {
        "fixedKeyCheckValue": "Foo"
      }
    }
  }
}

Expected Output:

{
  "randomKey1": {
    "randomKey2": [
      {
        "randomKeyUnderAnyLevel11": {
          "fixedKeyCheckPresence": {
            "randomeKeyUnderAnyLevel23": {
              "fixedKeyCheckValue": "Bar"
            }
          }
        }
      }
    ]
  },
  "randomKey11": {
    "fixedKeyCheckPresence": {
      "randomeKeyUnderAnyLevel123": {
        "fixedKeyCheckValue": "Bar"
      }
    }
  }
}

Tried: (.. | select(try has("fixedKeyCheckPresence")) | .fixedKeyCheckValue) |= (sub("^Foo$";"Bar"))

jq play: https://jqplay.org/s/_YlLSyTEc7

CodePudding user response:

You can combine walk with .. :

jq 'walk(
        (.fixedKeyCheckPresence? | .. |
         select(has("fixedKeyCheckValue")?).fixedKeyCheckValue) |= sub("^Foo$";"Bar")
    )' input.json

.fixedKeyCheckPresence? takes care of find the object key fixedKeyCheckPresence and leaves everything else intact.

Then under .fixedKeyCheckPresence, we enumerate all sub-nodes with .. and select the object containing fixedKeyCheckValue.

  • Related