• python中json.dumps使用的坑以及字符编码


    我们知道,python中的字符串分普通字符串和unicode字符串,一般从数据库中读取的字符串会自动被转换为unicode字符串

    下面回到重点,使用json.dumps时,一般的用法为:

    >>> obj={"name":"测试"}

    >>> json.dumps(obj)
    '{"name": "\u6d4b\u8bd5"}'

    >>> print json.dumps(obj)
    {"name": "u6d4bu8bd5"}

    >>> json.dumps(obj).encode("utf-8")
    '{"name": "\u6d4b\u8bd5"}'

    可以看到这里输出的字符串为普通字符串,但是里面的内容却是unicode字符串的内容,即使对结果进行encode("utf-8") ,因为这个字符串本身就已经编码过了,所有进行encode不会有变化

    要想得到字符串的真实表示,需要用到参数ensure_ascii=False(默认为True)

    >>> json.dumps(obj,ensure_ascii=False) 
    '{"name": "xe6xb5x8bxe8xafx95"}'

    >>> print json.dumps(obj,ensure_ascii=False)
    {"name": "测试"}

    坑:试试下面的用法(比如key是从数据库中读取的,则会以unicode字符串形式存在):

    >>> key=u"name"
    >>> obj={key:"测试"}  
    >>> json.dumps(obj,ensure_ascii=False)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib64/python2.6/json/__init__.py", line 237, in dumps
        **kw).encode(obj)
      File "/usr/lib64/python2.6/json/encoder.py", line 368, in encode
        return ''.join(chunks)
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 1: ordinal not in range(128)

    这是因为key和value不能以混合普通字符串和unicode字符串的形式存在

    改成下面则正常了(同时为普通字符串或同时为unicode字符串):

    >>> key=u"name"
    >>> obj={key:u"测试"}
    >>> json.dumps(obj,ensure_ascii=False)
    u'{"name": "u6d4bu8bd5"}'
    >>> obj={key.encode("utf-8"):u"测试".encode("utf-8")}
    >>> json.dumps(obj,ensure_ascii=False)              
    '{"name": "xe6xb5x8bxe8xafx95"}'

    另外说说还有一个参数default

    考虑下面的场景:

    >>> class Data:
    ...     def __init__(self):
    ...         self.name = ""
    ...         self.detail = ""
    ...

    >>> data=Data()
    >>> data.name="名字"
    >>> data.detail="细节"
    >>> obj={"data":data}
    >>> json.dumps(obj,ensure_ascii=False)

    会报下面的异常:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib64/python2.6/json/__init__.py", line 237, in dumps
        **kw).encode(obj)
      File "/usr/lib64/python2.6/json/encoder.py", line 367, in encode
        chunks = list(self.iterencode(o))
      File "/usr/lib64/python2.6/json/encoder.py", line 309, in _iterencode
        for chunk in self._iterencode_dict(o, markers):
      File "/usr/lib64/python2.6/json/encoder.py", line 275, in _iterencode_dict
        for chunk in self._iterencode(value, markers):
      File "/usr/lib64/python2.6/json/encoder.py", line 317, in _iterencode
        for chunk in self._iterencode_default(o, markers):
      File "/usr/lib64/python2.6/json/encoder.py", line 323, in _iterencode_default
        newobj = self.default(o)
      File "/usr/lib64/python2.6/json/encoder.py", line 344, in default
        raise TypeError(repr(o) + " is not JSON serializable")
    TypeError: <__main__.Data instance at 0x11e87e8> is not JSON serializable

    这是因为json.dumps不知道如何对Data对象进行序列化,需要定义一个函数,并赋给参数default:

    >>> def convert_to_builtin_type(obj):
    ...     d = {}
    ...     d.update(obj.__dict__)
    ...     return d
    ...

    >>> json.dumps(obj,ensure_ascii=False, default=convert_to_builtin_type)
    '{"data": {"name": "xe5x90x8dxe5xadx97", "detail": "xe7xbbx86xe8x8ax82"}}'
    >>> print json.dumps(obj,ensure_ascii=False, default=convert_to_builtin_type)
    {"data": {"name": "名字", "detail": "细节"}}

    def convert_to_builtin_type(obj):
        d = {}
        d.update(obj.__dict__)
        return d

  • 相关阅读:
    fastadmin编辑内容,有下拉选择关联的内容,自定义的参数去获取相应的下拉内容
    fastadmin 全手动添加规则
    微擎转移服务器后,出现 require()错误,解决方案
    laravel 路由
    装饰器练习
    python笔记(五)装饰器函数
    练习函数
    练习一
    python笔记(四)文件操作和函数
    py3和py2的差别(补充)
  • 原文地址:https://www.cnblogs.com/stubborn412/p/3818423.html
Copyright © 2020-2023  润新知