While it certainly could be accomplished via recursion given the nature of the problem, I think there's an even more elegant approach based on an idea I got a long time ago reading @Mike Brennan’s answer to another JSON-related question titled How to get string objects instead of Unicode from JSON?
The basic idea is to use the optional object_hook
parameter that both the json.load
and json.loads()
functions accept to watch what is being decoded and check it for the sought-after value (and replace it when it's encountered).The function passed will be called with the result of any JSON object literal decoded (i.e. a dict
) — in other words at any depth. What may not be obvious is that the dict
can also be changed if desired.
This nice thing about this overall approach is that it's based (primarily) on prewritten, debugged, and relatively fast code because it's part of the standard library. It also allows the object_hook
callback function to be kept relatively simple.
Here's what I'm suggesting:
import jsondef replace_placeholders(json_para, search_para, replace_para): # Local nested function. def decode_dict(a_dict): if search_para in a_dict.values(): for key, value in a_dict.items(): if value == search_para: a_dict[key] = replace_para return a_dict return json.loads(json_para, object_hook=decode_dict)result = replace_placeholders(json_para, 'placeholder_a', 'REPLACEMENT')print(json.dumps(result, indent=2))