通过DjangoJSONEncoder编码的UUID如何正确解码还原为UUID类型?
问题根源
你遇到的报错核心原因是对UUID做了重复的JSON序列化:Django的JSONField本身在存储数据时,就会默认使用DjangoJSONEncoder自动序列化内容,你提前手动调用encoder.encode(sample_uuid)相当于把UUID先转成了带双引号的JSON字符串,再存入JSONField,导致最终存储的是两层转义后的字符串,读取出的值会自带多余的双引号,不符合UUID的格式要求。
解决方案
方案1:解码现有已存储的错误数据
你可以通过以下两种方法把带引号的字符串还原为可用的UUID类型:
- 方法1:直接去除首尾多余的双引号
from uuid import UUID raw_uuid_str = test.extra_data["encoded_uuid"] # 去除首尾冗余的双引号 clean_uuid_str = raw_uuid_str.strip('"') decoded_uuid = UUID(clean_uuid_str)
- 方法2:对提前序列化的字符串做一次反序列化
import json from uuid import UUID raw_uuid_str = test.extra_data["encoded_uuid"] # 对应你之前的encode操作,做一次loads还原 decoded_uuid_str = json.loads(raw_uuid_str) decoded_uuid = UUID(decoded_uuid_str)
方案2:从根源修正存储逻辑(推荐)
不需要手动调用DjangoJSONEncoder编码UUID,JSONField原生支持自动序列化UUID类型,直接把UUID对象存入字段即可:
正确的存储代码
from uuid import uuid4 from .models import JsonTestModel sample_uuid = uuid4() # 直接传入UUID对象,Django会自动完成序列化 test = JsonTestModel.objects.create(extra_data={"encoded_uuid": sample_uuid})
读取代码
此时读取到的是标准格式的UUID字符串,可直接转换为UUID类型:
from uuid import UUID decoded_uuid = UUID(test.extra_data["encoded_uuid"])
进阶优化:自动完成UUID的序列化/反序列化
如果需要读取时直接得到UUID对象,无需手动转换,可以自定义JSONField的解码器:
import json from uuid import UUID from django.db import models from django.core.serializers.json import DjangoJSONEncoder class UUIDJSONDecoder(json.JSONDecoder): def __init__(self, *args, **kwargs): super().__init__(object_hook=self.uuid_hook, *args, **kwargs) def uuid_hook(self, dct): for k, v in dct.items(): if isinstance(v, str): try: dct[k] = UUID(v) except ValueError: pass return dct # 模型字段定义 class JsonTestModel(models.Model): extra_data = models.JSONField( encoder=DjangoJSONEncoder, decoder=UUIDJSONDecoder )
内容的提问来源于stack exchange,提问作者andrepz
相关产品推荐
相关产品推荐

