It is easy to change the format of an object which is not JSON serializable eg datetime.datetime.
My requirement, for debugging purposes, is to alter the way some cu
If you are only looking for serialization and not deserialization then you can process the object before sending it to json.dumps
. See below example
import datetime
import json
def is_inherited_from(obj, objtype):
return isinstance(obj, objtype) and not type(obj).__mro__[0] == objtype
def process_object(data):
if isinstance(data, list):
if is_inherited_from(data, list):
return process_object({"orig": list(data), "attrs": vars(data)})
new_data = []
for d in data:
new_data.append(process_object(d))
elif isinstance(data, tuple):
if is_inherited_from(data, tuple):
return process_object({"orig": tuple(data), "attrs": vars(data)})
new_data = []
for d in data:
new_data.append(process_object(d))
return tuple(new_data)
elif isinstance(data, dict):
if is_inherited_from(data, dict):
return process_object({"orig": list(data), "attrs": vars(data)})
new_data = {}
for k, v in data.items():
new_data[k] = process_object(v)
else:
return data
return new_data
def json_debug_handler(obj):
print("object received:")
print("\n\n")
if isinstance(obj, datetime.datetime):
return obj.isoformat()
class mDict(dict):
pass
class mList(list):
pass
def test_debug_json():
games = mList(['mario', 'contra', 'tetris'])
games.src = 'console'
scores = mDict({'dp': 10, 'pk': 45})
scores.processed = "unprocessed"
test_json = {'games': games, 'scores': scores, 'date': datetime.datetime.now()}
new_object = process_object(test_json)
print(json.dumps(new_object, default=json_debug_handler))
if __name__ == '__main__':
test_debug_json()
The output of the same is
{"games": {"orig": ["mario", "contra", "tetris"], "attrs": {"src": "console"}}, "scores": {"orig": ["dp", "pk"], "attrs": {"processed": "unprocessed"}}, "date": "2018-01-24T12:59:36.581689"}
It is also possible to override the JSONEncoder, but since it uses nested methods, it would be complex and require techniques discussed in below
Can you patch *just* a nested function with closure, or must the whole outer function be repeated?
Since you want to keep things simple, I would not suggest going that route