Napotkałem ten problem, gdy próbowałem zapisać model Peewee w PostgreSQL JSONField.
Po chwili zmagań oto ogólne rozwiązanie.
Kluczem do mojego rozwiązania jest przejrzenie kodu źródłowego Pythona i uświadomienie sobie, że dokumentacja kodu (opisana tutaj) już wyjaśnia, jak rozszerzyć istniejący json.dumps, aby obsługiwał inne typy danych.
Załóżmy, że masz model zawierający pola, których nie można serializować do formatu JSON, a model zawierający pole JSON oryginalnie wygląda następująco:
class SomeClass(Model):
json_field = JSONField()
Po prostu zdefiniuj niestandardowy JSONEncoder w ten sposób:
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)
A potem po prostu użyj go w swoim JSONField jak poniżej:
class SomeClass(Model):
json_field = JSONField(dumps=CustomJsonEncoder.json_dumper)
Kluczem jest powyższa metoda default(self, obj). Do każdej pojedynczej skargi ... is not JSON serializable otrzymanej od Pythona po prostu dodaj kod obsługujący typ niemożliwy do serializacji do JSON (taki jak Enum lub datetime)
Na przykład oto jak obsługuję klasę dziedziczącą z 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)
Wreszcie, po zaimplementowaniu kodu jak powyżej, możesz po prostu przekonwertować dowolne modele Peewee na obiekt nadający się do szeregowania w JSON, jak poniżej:
peewee_model = WhateverPeeweeModel()
new_model = SomeClass()
new_model.json_field = model_to_dict(peewee_model)
Chociaż powyższy kod był (w pewnym stopniu) specyficzny dla Peewee, ale myślę:
- Ogólnie ma to zastosowanie do innych ORM (Django itp.).
- Ponadto, jeśli zrozumiałeś, jak działa
json.dumps, to rozwiązanie działa również ogólnie z Pythonem (bez ORM)
Wszelkie pytania proszę pisać w sekcji komentarzy. Dzięki!
person
sivabudh
schedule
30.07.2018
import jsonszobacz odpowiedź poniżej — działa doskonale - person tswaehn   schedule 02.04.2020.to_dict()lub coś, co można wywołać na obiekcie, zanim zostanie on przekazany do modułu, który spróbuje go serializować. - person Felix B.   schedule 01.09.2020varsw połączeniu zjson.dumps(zobacz moją odpowiedź stackoverflow.com/a/64469761/1587520 ) - person user1587520   schedule 23.11.2020