'JQ - Deep child value replace through wildcard search and merge to the original JSON

My question is similar to Unix jq parsing wildcards but want to merge to the original JSON.

Say, input JSON:

{
  "a": {
    "1": {
      "c": "text1"
    },
    "999": {
      "c": "text99"
    }
  }
}

I want to manipulate the inner "c": "text1" and modify it to "c": "newtext". But, also need to merge with the original JSON. IOW, it is not about extracting, but about manipulating.

Expected output:

{
  "a": {
    "1": {
      "c": "newtext"
    },
    "999": {
      "c": "text99"
    }
  }
}

I tried:

.. | .c? |= (sub("^text1$";"newtext"))

But, it throws null (null) cannot be matched, as it is not a string

jqplay: https://jqplay.org/s/2nFAus6Umz



Solution 1:[1]

Just walk the path with the expression to select an object type when .c equals to your desired value

jq 'walk(if type == "object" and .c == "text1" then .c |= "newtext" else . end)'

jqplay demo

Solution 2:[2]

Along the lines of your attempt:

(.. | objects | select(has("c")) | .c) |= (sub("^text1$";"newtext"))

or in order of increasing brevity:

(.. | select(try has("c")) | .c) |= (sub("^text1$";"newtext"))

(.. | select(has("c")?) | .c) |= (sub("^text1$";"newtext"))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Inian
Solution 2 peak