ฉันวิ่งเข้าไปในปัญหานี้เมื่อฉันพยายามที่จะเก็บรูปแบบแคระเข้า JSONField
PostgreSQL
หลังจากดิ้นรนไประยะหนึ่งแล้วนี่เป็นคำตอบทั่วไป
กุญแจสำคัญในการแก้ไขปัญหาของฉันคือการใช้ซอร์สโค้ดของ 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 แต่ฉันคิดว่า:
- สามารถใช้ได้กับ ORM อื่น ๆ (Django ฯลฯ ) โดยทั่วไป
- นอกจากนี้หากคุณเข้าใจวิธีการ
json.dumps
ทำงานโซลูชันนี้ก็สามารถใช้ได้กับ Python (sans ORM) โดยทั่วไปเช่นกัน
คำถามใด ๆ โปรดโพสต์ในส่วนความเห็น ขอบคุณ!