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から受け取ったすべての苦情に対して、unserializable-to-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に(ある程度)固有のものでしたが、私は次のように考えています。
- 一般的に他のORM(Djangoなど)に適用できます
- また、どのように
json.dumps
機能するかを理解している場合、このソリューションは一般にPython(sans ORM)でも機能します
質問があれば、コメント欄に投稿してください。ありがとう!