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
Advertisement
Answer
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
.