Json与JsonResponse

json实现不支持转换数据类型得转换

当我们用json模块的dumps把一种json模块不支持的数据类型进行转换成json字符串的时候,会报错

TypeError: Object of type 'datetime' is not JSON serializable

“datetime 类型的对象不能被json解析”

但是现在的业务逻辑是我们非要让他能够解析,这时候看他的源码。

先进入到dumps的源码之中

def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):

看见里面有一个 cls = None,这时候先不要看cls是什么,然后往下看,找到了一个

 if cls is None:
        cls = JSONEncoder

点进去 JSONEncoder 看他的源码,

    def default(self, o):
        """Implement this method in a subclass such that it returns
        a serializable object for ``o``, or calls the base implementation
        (to raise a ``TypeError``).

        For example, to support arbitrary iterators, you could
        implement default like this::

            def default(self, o):
                try:
                    iterable = iter(o)
                except TypeError:
                    pass
                else:
                    return list(iterable)
                # Let the base class default method raise the TypeError
                return JSONEncoder.default(self, o)

        """
        raise TypeError("Object of type '%s' is not JSON serializable" %
                        o.__class__.__name__)

看到了这句抛出异常,和我们的报错是一样的,所以,我们这时候可以通过重写这个 JSONEncoder类的default方法,来实现我们要的业务逻辑。

class MyJsonClass(json.JSONEncoder):
     def default(self, o):
         if isinstance(o,datetime):  # 如果o不是json默认能够序列化 你就在该方法内给他处理成json能够转的类型
             return o.strftime('%Y-%m-%d')
         else:
             super().default(self,o)

比如我们要dumps的对象是一个datetime类型的数据,那么这里的isinstance第二个参数就写这个,判断来的对象是不是他的子类,是的话,就手动给他转换了,再返回,当然不是这种类型的时候要继续使用之前的功能,所以调用父类的default方法。

d = {'ctime':datetime.today()}
print(json.dumps(d,cls=MyJsonClass))

这时候在这里面写一个cls=MyJsonClass,就可以了,再看下去源码就是讲json是怎么序列化的了。

JsonResponse

Django有一个简单的方法,不需要我们去导入json模块,然后序列化了,

先导入以下模块

from django.http import JsonResponse

然后再调用就可以了

 l = [1,2,3,4,5,5,6]
    return JsonResponse(user,json_dumps_params={'ensure_ascii':False})
   

json_dumps_params是什么?进JsonResponse的源码看一下。

class JsonResponse(HttpResponse):

    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs):
        if safe and not isinstance(data, dict):
            raise TypeError(
                'In order to allow non-dict objects to be serialized set the '
                'safe parameter to False.'
            )
        if json_dumps_params is None:
            json_dumps_params = {}
        kwargs.setdefault('content_type', 'application/json')
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super(JsonResponse, self).__init__(content=data, **kwargs)

Django模块就是贱,叫我们不要导入json模块,用他的JsonResponse,而他自己

JsonResponse实现的方法却依然是基于json模块的,好恶心啊,**json_dumps_params就是参数咯,所以我们只需要像上面那样写,带一个字典,它会把它打散成关键字参数,这时候就可以写入 ensure_ascii':False 了,他的作用是不让中文字符直接被转码成字节了。

现在进行一个操作:

l = [1,2,3,4,5,5,6]
    return JsonResponse(l)

结果却报错了

错误信息

TypeError at /index/
In order to allow non-dict objects to be serialized set the safe parameter to False.
"为了允许序列化非dict对象,请将安全参数设置为False。"

那我们就去设置就好了

l = [1,2,3,4,5,5,6]
    return JsonResponse(l,safe=False)

这时候就不会报错了。

JsonResponse默认只支持序列化字典 如果你想序列化其他类型(json能够支持的类型) 你需要将safe参数由默认的True改成False

posted @ 2019-10-23 22:54  chanyuli  阅读(1105)  评论(0编辑  收藏  举报