У меня есть дерево объектов Python, которое я хочу сериализовать. Его структура примерно такая:
{
"regular_object": {
...
},
"regular_field": ...
"special_object": {
"f1": "v1",
"f2": v2,
...
"fn": "vn"
}
}
Я хочу сериализовать такое дерево объектов, чтобы оно форматировалось в виде JSON:
{
"regular_object": {
...
},
"regular_field": ...
"special_object": { "f1": "v1", "f2": v2, ..., "fn": "vn" }
}
Другими словами, я хочу смешанное форматирование на основе содержимого форматируемого объекта .
Я попытался поиграться с json.JSONEncoder
, переопределив его метод default
и используя объект пользовательского класса для хранения содержимого special_object
, чтобы вызывался пользовательский default
, примерно так:
class SpecialObject:
def __init__(self, attrs: dict):
self.attrs = attrs
class SpecialEncoder(json.JSONEncoder):
def default(self, o):
JE = json.JSONEncoder
if isinstance(o, SpecialObject):
return f"{{ ', '.join([f'{JE.encode(self, el[0])}: {JE.encode(el[1])}' for el in o.attrs.items()]) }}"
else:
return super().default(o)
Но похоже, что JSONEncoder
кодирует возвращаемое default
возвращаемое значение снова , поэтому строка, которую я генерирую для моего пользовательского типа, сериализуется в виде строки, с выводом, похожим на:
{
...
"special_object": "{ \"f1\": \"v1\", ..., \"fn\": \"vn\" }"
}
что явно не то, что я имел в виду. Я также попытался переопределить метод JSONEncoder.encode
, как показывают некоторые ответы, но этот метод никогда не вызывается из самого JSONEncoder
.
Я нашел несколько подходов к решению, казалось бы, похожих проблем, но представленные там решения слишком чудовищно выглядят и слишком сложны для такой задачи, как моя.
Есть ли способ достичь того, что мне нужно, всего за одну-две дюжины строк кода, не вдаваясь слишком глубоко в кишечник JSONEncoder
? Это не должно быть универсальное решение, просто что-то, что я мог бы быстро исправить и которое может работать только для одного случая.