others - 在 json.dumps 中将UTF8文本保存为 UTF8,而不是 将u作为转义序列

代码示例:


>>> import json
>>> json_stringv json.dumps("ברי צקלה")
>>> print json_string
"u05d1u05e8u05d9 u05e6u05e7u05dcu05d4"

问题:它不是人类可读的,我的用户希望通过JSON转储来验证甚至编辑文本文件。 (我不想使用XML )

是否可以将对象序列化为utf-8 json字符串(代替uXXXX )?

这没有帮助:


>>> output = json_string.decode('string-escape')
"u05d1u05e8u05d9 u05e6u05e7u05dcu05d4"

这是有效的,但是如果子对象是一个python而不是UTF-8,则它将转储成一堆垃圾:


>>> #### ok:
>>> s= json.dumps("ברי צקלה", ensure_ascii=False) 
>>> print json.loads(s) 
ברי צקלה

>>> #### NOT ok:
>>> d={ 1:"ברי צקלה", 2: u"ברי צקלה" }
>>> print d
{1: 'xd7x91xd7xa8xd7x99 xd7xa6xd7xa7xd7x9cxd7x94', 
 2: u'xd7x91xd7xa8xd7x99 xd7xa6xd7xa7xd7x9cxd7x94'}
>>> s = json.dumps( d, ensure_ascii=False, encoding='utf8')
>>> print json.loads(s)['1']
ברי צקלה
>>> print json.loads(s)['2']
××¨× ×¦×§××

我搜索了json.dumps文档,但是找不到有用的东西。

感谢大家:)

时间:

使用ensure_ascii=False切换到json.dumps(),然后手动将该值编码为UTF-8 :


>>> json_string = json.dumps(u"ברי צקלה", ensure_ascii=False).encode('utf8')
>>> json_string
'"xd7x91xd7xa8xd7x99 xd7xa6xd7xa7xd7x9cxd7x94"'
>>> print json_string
"ברי צקלה"

如果要将此文件写入文件,可以使用io.open()而不是open()生成编写文件对象的文件对象,


with io.open('filename', 'w', encoding='utf8') as json_file:
 json.dump(u"ברי צקלה", json_file, ensure_ascii=False)

在python 3中,open()是io.open()的别名,请注意,有一个json模块中的错误ensure_ascii=False标志可以生成unicodestr对象的混合,那么,Python 2的解决方法是:


with io.open('filename', 'w', encoding='utf8') as json_file:
 data = json.dumps(u"ברי צקלה", ensure_ascii=False)
 # unicode(data) auto-decodes data to unicode if str
 json_file.write(unicode(data))

如果要传递(在python 2中输入str,在python 3中输入bytes)编码到UTF-8的字节字符串,请确保同时设置encoding关键字:


>>> d={ 1:"ברי צקלה", 2: u"ברי צקלה" }
>>> d
{1: 'xd7x91xd7xa8xd7x99 xd7xa6xd7xa7xd7x9cxd7x94', 2: u'u05d1u05e8u05d9 u05e6u05e7u05dcu05d4'}

>>> s=json.dumps(d, ensure_ascii=False, encoding='utf8')
>>> s
u'{"1":"u05d1u05e8u05d9 u05e6u05e7u05dcu05d4","2":"u05d1u05e8u05d9 u05e6u05e7u05dcu05d4"}'
>>> json.loads(s)['1']
u'u05d1u05e8u05d9 u05e6u05e7u05dcu05d4'
>>> json.loads(s)['2']
u'u05d1u05e8u05d9 u05e6u05e7u05dcu05d4'
>>> print json.loads(s)['1']
ברי צקלה
>>> print json.loads(s)['2']
ברי צקלה

请注意,第二个例子是无效 你将UTF-8字节作为一个unicode文本,这永远不能工作:


>>> s = u'xd7x91xd7xa8xd7x99 xd7xa6xd7xa7xd7x9cxd7x94'
>>> print s
××¨× ×¦×§××
>>> print s.encode('latin1').decode('utf8')
ברי צקלה

unicode-escape怎么样?


>>> d = {1:"ברי צקלה", 2: u"ברי צקלה"}
>>> json_str = json.dumps(d).decode('unicode-escape').encode('utf8')
>>> print json_str
{"1":"ברי צקלה","2":"ברי צקלה"}

Peters的python 2解决方法在边缘情况下失败:


d = {u'keyword': u'bad credit xe7redit cards'}
with io.open('filename', 'w', encoding='utf8') as json_file:
 data = json.dumps(d, ensure_ascii=False).decode('utf8')
 try:
 json_file.write(data)
 except TypeError:
 # Decode data to Unicode first
 json_file.write(data.decode('utf8'))

UnicodeEncodeError: 'ascii' codec can't encode character u'xe7' in position 25: ordinal not in range(128)

它在第3行的.decode('utf8')崩溃,通过避免这个步骤以及ascii的特殊套管来修复这个问题:


with io.open('filename', 'w', encoding='utf8') as json_file:
 data = json.dumps(d, ensure_ascii=False, encoding='utf8')
 json_file.write(unicode(data))

cat filename
{"keyword":"bad credit çredit cards"}

就像Martijn所指出的那样,在json dumps中使用suresure_ascii =False是解决此问题的正确方向,但是,这可能会引发异常:


UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 1: ordinal not in range(128)

你需要在site.py或sitecustomize.py中设置额外设置才能正确设置你的sys.getdefaultencoding(),site.py在lib/python2.7/下,sitecustomize.py在lib/python2.7/site-packages下。

如果你喜欢使用sitecustomize.py,如果你没有创建它,它可能不存在,简单地放置以下行:


import sys
reload(sys)
sys.setdefaultencoding('utf-8')

然后,你可以使用utf-8格式进行一些中文json输出,例如:


name = {"last_name": u"王"}
json.dumps(name, ensure_ascii=False)

你将得到一个utf-8编码的字符串,而不是转义的json字符串。

验证你的默认编码:


print sys.getdefaultencoding()

请注意,在交互式python控制台上不能执行sys.setdefaultencoding("utf-8")。

...