- 💖 作者简介:大家好,我是Zeeland,全栈领域优质创作者。
- 📝 CSDN主页:Zeeland🔥
- 📣 我的博客:Zeeland
- 📚 Github主页: Undertone0809 (Zeeland) (github.com)
- 🎉 支持我:点赞👍+收藏⭐️+留言📝
- 📣 系列专栏:django开发手册🍁
- 💬介绍:The mixture of software dev+Iot+ml+anything🔥
Django系列专栏
- 【django开发手册】Django 中使用自定义用户模型:一个比自带 User 更强的选择
- 【django开发手册】如何使用select_related进行一次连表查询
- 【django开发手册】drf通过添加自定义字段优化DRF序列化器,轻松实现高速API
- 【django开发手册】解决admin添加外键下拉显示外键的问题
- 【Django Rest Framework优化实践】ResponseResult、异常处理方法详解
- 【DRF】深度分析枚举类型在DRF中的序列化问题及解决方案
- 【django开发手册】关于django admin添加表信息的时候外键无法为空的问题解决方案
- 【django开发手册】django admin如何显示外键对应的字段
- 【django开发手册】DRF外键模型查询没有信息?教你实现序列化返回
前言
- 在RESTful API的开发过程中,JSON序列化是一个常见的问题。特别是在Django REST Framework (DRF)的开发中,有时会遇到某些数据类型无法被JSON序列化的情况,导致返回错误的响应结果。这对于开发者来说是一个令人沮丧的问题,特别是当许多代码看起来都是正确的时候,很难找到问题出在哪里。
- 在本文中,我们将讨论RDF开发中的JSON序列化问题以及解决方案。具体而言,我们会讨论一个常见的问题:枚举类型无法被JSON序列化。下面,我们将探索这个问题的本质,以及如何解决它。
- 我正在进行RDF开发,我正在尝试访问 models
Company
的数据,但是报错了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
的值进行简单的修改来解决它。
解决方案
-
问题出在
ResponseResult
的to_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序列化。