本文共 1839 字,大约阅读时间需要 6 分钟。
我们知道JSON字符串是目前流行的数据交换格式,在pyhton中我们通过json模块,将常用的数据类型转化为json字符串。但是,json支持转化的数据类型是有限的。
比如,我们通过ORM从数据库查询出的结果,试图通过json序列化:
from .models import UserInfodef 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
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)
将返回的结果放到校验结果如下:
[ { "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.dumps
源码,发现序列化时,用到了一个参数cls = JSONEncoder
,我们可以继承它,自定义一个类,重写它的default
方法,来处理我们需要的数据类型。比如自定义对时间对象进行转化:
import jsonfrom datetime import datefrom datetime import datetimeclass 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
:
是不是成功处理了呢