Я зіткнувся з цією проблемою, коли спробував зберегти модель 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)
Будь-які питання, будь ласка, опублікуйте в розділі коментарів. Дякую!