Я зіткнувся з цією проблемою, коли спробував зберегти модель Peewee в PostgreSQL JSONField.
Пробуючи деякий час, ось загальне рішення.
Ключ до мого рішення проходить через вихідний код Python і розуміє, що документація на коди (описана тут ) вже пояснює, як розширити існуючі json.dumpsдля підтримки інших типів даних.
Припустимо, у вас є модель, яка містить деякі поля, не серіалізаційні для JSON, а модель, що містить поле JSON, спочатку виглядає так:
class SomeClass(Model):
json_field = JSONField()
Просто визначте такий звичай JSONEncoder:
class CustomJsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, SomeTypeUnsupportedByJsonDumps):
return < whatever value you want >
return json.JSONEncoder.default(self, obj)
@staticmethod
def json_dumper(obj):
return json.dumps(obj, cls=CustomJsonEncoder)
А потім просто використовуйте його так, JSONFieldяк показано нижче:
class SomeClass(Model):
json_field = JSONField(dumps=CustomJsonEncoder.json_dumper)
Ключовим є default(self, obj)метод вище. Для кожної ... is not JSON serializableскарги, яку ви отримуєте від Python, просто додайте код для обробки несеріалізаційного типу JSON (наприклад, Enumабоdatetime )
Наприклад, ось як я підтримую спадкування класу від Enum:
class TransactionType(Enum):
CURRENT = 1
STACKED = 2
def default(self, obj):
if isinstance(obj, TransactionType):
return obj.value
return json.JSONEncoder.default(self, obj)
Нарешті, з реалізованим кодом, як описано вище, ви можете просто перетворити будь-які моделі Peewee в об'єкт, який можна встановити за допомогою JSON, як нижче:
peewee_model = WhateverPeeweeModel()
new_model = SomeClass()
new_model.json_field = model_to_dict(peewee_model)
Хоча код вище був (дещо) специфічним для Peewee, але я думаю:
- Це застосовно до інших ОРМ (Джанго тощо) загалом
- Крім того, якщо ви зрозуміли, як
json.dumpsпрацює, це рішення також працює і з Python (sans ORM)
Будь-які питання, будь ласка, опублікуйте в розділі коментарів. Дякую!