【DRF】深度分析枚举类型在DRF中的序列化问题及解决方案

前言

  • 在RESTful API的开发过程中,JSON序列化是一个常见的问题。特别是在Django REST Framework (DRF)的开发中,有时会遇到某些数据类型无法被JSON序列化的情况,导致返回错误的响应结果。这对于开发者来说是一个令人沮丧的问题,特别是当许多代码看起来都是正确的时候,很难找到问题出在哪里。
  • 在本文中,我们将讨论RDF开发中的JSON序列化问题以及解决方案。具体而言,我们会讨论一个常见的问题:枚举类型无法被JSON序列化。下面,我们将探索这个问题的本质,以及如何解决它。
  • 我正在进行RDF开发,我正在尝试访问 modelsCompany的数据,但是报错了TypeError at /company/ Object of type ResponseMsg is not JSON serializable,相关代码如下。
# response_result.py  
from enum import Enum  
from rest_framework.response import Response  
  
  
class ResponseMsg:  
    SUCCESS = 'success'  
    BAD_REQUEST = 'bad request'  
    UNAUTHORIZED = 'unauthorized'  
    FORBIDDEN = 'forbidden'  
    NOT_FOUND = 'not found'  
    SERVER_ERROR = 'server error'  
  
  
class ResponseCode(Enum):  
    SUCCESS = 200  
    BAD_REQUEST = 400  
    UNAUTHORIZED = 401  
    FORBIDDEN = 403  
    NOT_FOUND = 404  
    SERVER_ERROR = 500  
  
  
class ResponseResult:  
    """  
    使用了DRF自带的Response类来封装返回结果。Response类在默认情况下会将数据序列化成JSON格式并返回,  
    可以自动设置HTTP响应头和状态码等信息,方便管理。在ResponseResult类中,我们加入了to_response方  
    法,将当前的ResponseResult实例转换成Response实例返回给DRF框架。此外,我们还对__getitem__和  
    __setitem__方法进行了重载,方便使用。  
    """  
    def __init__(self, code=ResponseCode.SUCCESS, data=None, msg=ResponseMsg.SUCCESS):  
        self.code = code.value  
        self.data = data  
        self.msg = msg  
  
    def __getitem__(self, key):  
        return getattr(self, key)  
  
    def __setitem__(self, key, value):  
        setattr(self, key, value)  
  
    def to_response(self):  
        return Response(data=self.__dict__)
    
# views.py  
class MenuViewSet(viewsets.ModelViewSet):  
    queryset = models.SysMenu.objects.all()    serializer_class = MenuSerialize  
    def list(self, request, *args, **kwargs):  
        params = request.query_params        return params.get('')  
# models.py

class Company(models.Model):  
    class Meta:  
        verbose_name = "公司管理"  # 模型名称(单数)  
        verbose_name_plural = verbose_name  # 模型名称(复数)  
  
    # django admin的显示值  
    def __str__(self):  
        return self.company_name  
  
    company_id = models.AutoField(primary_key=True, verbose_name='公司ID')  
    company_name = models.CharField(max_length=255, verbose_name='公司名称', unique=True)  
    company_descrption = models.CharField("公司描述", null=True, blank=True, max_length=255)  
    creator_id = models.IntegerField(null=True, blank=True, verbose_name='创建者ID')  
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')  
    update_id = models.IntegerField(null=True, blank=True, verbose_name='更新者ID')  
    update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')  
    deleted_choice = (  
        (True, "是"),  
        (False, "否")  
    )  
    is_deleted = models.BooleanField("逻辑删除", default=False, choices=deleted_choice)
    
  • 当我们在RDF中使用枚举类型时,它们被视为内置类型并被DRF序列化。问题在于,内置类型无法被JSON序列化,因此在许多情况下,前端会接收到错误的响应结果,例如:
TypeError: Object of type ResponseMsg is not JSON serializable
  • 该错误表示ResponseMsg值的枚举类型无法被JSON序列化。但是,我们可以对ResponseMsg的值进行简单的修改来解决它。

解决方案

  • 问题出在ResponseResultto_response方法中,self.__dict__返回的结果包含了一个ResponseMsg的值,而这个值无法被JSON序列化。可以考虑将ResponseMsg的值改为普通的字符串,就可以避免这个问题。

  • 可以将ResponseMsg的值改为普通的字符串,比如:

class ResponseMsg:
    SUCCESS = 'success'
    BAD_REQUEST = 'bad request'
    UNAUTHORIZED = 'unauthorized'
    FORBIDDEN = 'forbidden'
    NOT_FOUND = 'not found'
    SERVER_ERROR = 'server error'
  • 这样子就可以完美解决这个问题了

为什么ResponseCode不会报错但是ResponseMsg会报这个序列化错误?

  • 至于为什么ResponseCode不会报错,是因为这个枚举类里只有整型值,可以被JSON序列化。

猜你喜欢

转载自blog.csdn.net/linZinan_/article/details/129862594