zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Unity3d获取APK签名及公钥的方法
    NGUI屏幕自适应
    转:Firefox中firebug和xpath checker工具的使用
    判断输入的手机号和价格是否合法
    IOS 四种保存数据的方式
    IOS开发控制器之间传值的几种小方法
    AlertView的三种弹窗模式
    多线程之NSThread、NSOperation及GCD
    IOS Key-Value Observing (KVO)
    UILabel的相关属性设置
  • 原文地址:https://www.cnblogs.com/chanyuli/p/11729660.html
Copyright © 2011-2022 走看看