python中json.dumps使⽤的坑以及字符编码
我们知道,python中的字符串分普通字符串和unicode字符串,⼀般从数据库中读取的字符串会⾃动被转换为unicode字符串
下⾯回到重点,使⽤json.dumps时,⼀般的⽤法为:
>>> obj={"name":"测试"}
>>> json.dumps(obj)
'{"name": "
>>> print json.dumps(obj)
{"name": "\u6d4b\u8bd5"}
>>> json.dumps(obj).encode("utf-8")
'{"name": "
可以看到这⾥输出的字符串为普通字符串,但是⾥⾯的内容却是unicode字符串的内容,即使对结果进⾏encode("utf-8") ,因为这个字符串本⾝就已经编码过了,所有进⾏encode不会有变化
要想得到字符串的真实表⽰,需要⽤到参数ensure_ascii=False(默认为True):
>>> json.dumps(obj,ensure_ascii=False)
'{"name": "\xe6\xb5\x8b\xe8\xaf\x95"}'
>>> 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": "\u6d4b\u8bd5"}'
>>> obj={de("utf-8"):u"测试".encode("utf-8")}
>>> json.dumps(obj,ensure_ascii=False)
'{"name": "\xe6\xb5\x8b\xe8\xaf\x95"}'
另外说说还有⼀个参数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
unicode所有字符
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": "\xe5\x90\x8d\xe5\xad\x97", "detail": "\xe7\xbb\x86\xe8\x8a\x82"}}'
>>> 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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。