Ho riscontrato questo problema quando ho provato a memorizzare il modello di Peewee in PostgreSQL JSONField
.
Dopo aver lottato per un po ', ecco la soluzione generale.
La chiave della mia soluzione sta passando attraverso il codice sorgente di Python e rendendosi conto che la documentazione del codice (descritta qui ) spiega già come estendere l'esistente json.dumps
per supportare altri tipi di dati.
Supponiamo che tu abbia attualmente un modello che contiene alcuni campi che non sono serializzabili su JSON e che il modello che contiene il campo JSON originariamente assomiglia a questo:
class SomeClass(Model):
json_field = JSONField()
Basta definire un'usanza JSONEncoder
come questa:
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)
E poi usalo nel tuo JSONField
like qui sotto:
class SomeClass(Model):
json_field = JSONField(dumps=CustomJsonEncoder.json_dumper)
La chiave è il default(self, obj)
metodo sopra. Per ogni singolo ... is not JSON serializable
reclamo ricevuto da Python, basta aggiungere il codice per gestire il tipo non serializzabile-JSON (come Enum
odatetime
)
Ad esempio, ecco come supporto una classe che eredita da 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)
Infine, con il codice implementato come sopra, puoi semplicemente convertire qualsiasi modello Peewee in un oggetto seriazabile JSON come sotto:
peewee_model = WhateverPeeweeModel()
new_model = SomeClass()
new_model.json_field = model_to_dict(peewee_model)
Anche se il codice sopra era (in qualche modo) specifico di Peewee, ma penso:
- È applicabile ad altri ORM (Django, ecc.) In generale
- Inoltre, se hai capito come
json.dumps
funziona, questa soluzione funziona anche con Python (sans ORM) in generale
Per qualsiasi domanda, si prega di pubblicare nella sezione commenti. Grazie!