python中json.dumps使用的坑以及字符編碼


我們知道,python中的字符串分普通字符串和unicode字符串,一般從數據庫中讀取的字符串會自動被轉換為unicode字符串

下面回到重點,使用json.dumps時,一般的用法為:

>>> obj={"name":"測試"}

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

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

>>> 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": "\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={key.encode("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
    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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM