Django中QuerySet对象的JSON序列化解决方案

江岸
江岸
发布时间:2026-10-13| 4人浏览过
原创

本文探讨Django中QuerySet对象无法直接序列化为JSON字符串的问题。通过对比Django内置serializers模块与自定义JSONEncoder两种方案,分析各自的优缺点。前者暴露表结构且不支持连表,后者灵活但需手动处理类型,帮助开发者选择合适的数据交换方式。

QuerySet序列化问题背景

JSON字符串是当前广泛采用的数据交换格式。在Python中,利用内置的json模块可以将常见数据类型转换为JSON字符串,但需要注意的是,JSON支持的数据类型范围有限。

例如,当尝试直接对通过ORM从数据库查询得到的结果进行JSON序列化时,往往会遇到问题。


from .models import UserInfo

def index(request):
  user_list = UserInfo.objects.all()
  import json
  return HttpResponse(json.dumps(user_list))
  # TypeError: Object of type 'QuerySet' is not JSON serializable

此时会抛出错误,提示QuerySet对象不是JSON可序列化的类型。面对这种情况,有哪些可行的解决策略?

如果采用values方法进行查询,如UserInfo.objects.values("name"),虽然返回的仍是QuerySet对象,但其内部结构表现为列表嵌套字典的形式,例如<QuerySet [{'name': 'egon'}, {'name': 'sb'}]>。针对此类情况,只需使用list()方法将QuerySet转换为列表,即可直接通过json.dumps()完成序列化操作。

使用serializers模块处理

方法一:使用serializers模块


def index(request):
  user_list = UserInfo.objects.all()
  from django.core import serializers
  user_list_json = serializers.serialize("json", user_list)
  return HttpResponse(user_list_json)

将上述方法生成的结果放入bejson工具进行校验,结果如下所示。


[
 {
  "model": "app01.userinfo",
  "pk": 1,  
  "fields": {
    "name": "egon",
    "pwd": "123"
  }
},
{
  "model": "app01.userinfo",
  "pk": 2,
  "fields": {
    "name": "sb",
    "pwd": "123"
  }
}
]

注:pk字段代表主键,既可以是默认的id字段,也可以是用户自定义的主键字段。

观察序列化后的结果可以发现,这种方式会将服务端数据库的表名完全暴露;此外,serializers模块不支持连表序列化,只能获取关联表的id。因此,我们尝试另一种新的处理方式。

自定义JSON处理器方案

方法二:自定义JSON处理器

查看json.dumps的源码可知,序列化过程中使用了一个名为cls = JSONEncoder的参数。我们可以继承该类并自定义一个新类,重写其default方法,以处理特定数据类型。例如,可以自定义对时间对象进行转换的逻辑。


import json
from datetime import date
from datetime import datetime

class JsonCustomEncoder(json.JSONEncoder):

  def default(self, field):

    if isinstance(field, datetime):
      return field.strftime('%Y-%m-%d %H:%M:%S')
    elif isinstance(field, date):
      return field.strftime('%Y-%m-%d')
    else:
      return json.JSONEncoder.default(self, field)

接下来,我们尝试对一个datetime对象执行序列化操作。


def index(request):
  now = datetime.now()
  import json
  return HttpResponse(json.dumps(now, cls=JsonCustomEncoder))

再次访问http://127.0.0.1:8000/index.html,观察输出结果。

补充:Django ORM序列化细节

补充知识:Django ORM对象Json序列化问题

在实际开发中可能会遇到一个问题:在使用json.dumps()序列化Django ORM的Queryset对象并传递给前端时,程序会报错。

Object of type 'QuerySet' is not JSON serializable

在Python中,常用的json模块是基于simplejson改进而来的。该模块主要提供dump和load函数来实现dict与字符串之间的序列化与反序列化,这通常能很方便地完成数据转换。然而,当前的难点在于,这个json模块无法直接序列化Django models中的对象实例。

经过搜索查找,发现有以下解决方案。

可以使用django.core自带的serializers模块来处理。


#django ORM的 Queryset对象默认无法被直接json.dumps()序列化,django.core提供的serializers模块提供将其序列化成str类型
#的功能,serializers处理后,再次json.dumps传给前端,前端需要经过两次json.Parse()处理,才能得到原对象类型,但是格式发
#生了变化,需要按新的方式取索引.例如:obj['pk']取主键,obj['fields']["caption"]取obj的caption字段
由QuerySet:[<Business: Business object>]
变为了:
[{"model": "cmdb.business", "pk": 1, "fields": {"caption": "develop"}}]

这样前端就可以正常获取数据了,不过需要注意的是,此字段需要经过两次json.Parse()处理才能解析。

至于使用models.Host.objects.get(id=xx)方式获取到的单个对象(而非Queryset对象),serializers默认也无法直接处理。针对这一问题,可以通过自定义json方法来实现dumps序列化。

json默认仅支持Python原生的list、tuple、dict数据类型对象的序列化。若需扩展对其他类型对象的序列化功能,可以按照以下方式修改代码。


import json as default_json
from json.encoder import JSONEncoder


class BaseResponse(object):
  def __init__(self):
    self.status = True
    self.message = None
    self.data = None
    self.error = None
o=BaseResponse()

class JsonCustomEncoder(JSONEncoder):
  def default(self, o):
    if isinstance(o, BaseResponse):
      return o.__dict__
    return JSONEncoder.default(self, o)

o1=json.dumps(o,cls=JsonCustomEncoder)


>>> print(o1)
{"message": null, "error": null, "data": null, "status": true}
>>> print(type(o1))
<class 'str'>
#在序列化时指定cls参数,cls=自定义的序列化类,在自定义序列化类的default方法中判断,如果是指定的类的实例的话,则将该类转换成dict格式返回,若指定类的实例,则使用json模块默认的序列化方法。最终得到的return值为str类型。

以上关于Django JSON序列化的内容就是小编分享给大家的全部信息,希望能对大家有所帮助,也希望大家多多支持本站。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。