将json.dumps中的utf-8文本保存为UTF8,而不是\ u转义序列

问题:

示例代码:

>>> import json
>>> json_string = json.dumps("ברי צקלה")
>>> print json_string
"\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"

问题:它不是人类可读的。我的(智能)用户想要使用JSON转储来验证甚至编辑文本文件。 (我宁愿不使用XML)
有没有办法将对象序列化为utf-8 json字符串(而不是\ uXXXX)?
这没有帮助:

>>> output = json_string.decode('string-escape')
"\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"

这个作品,但如果任何子对象是一个python-unicode而不是utf-8,它会转储垃圾:

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

>>> #### NOT ok:
>>> d={ 1: "ברי צקלה", 2: u"ברי צקלה" }
>>> print d
{1: '\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94', 
 2: u'\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94'}
>>> s = json.dumps( d, ensure_ascii=False, encoding='utf8')
>>> print json.loads(s)['1']
ברי צקלה
>>> print json.loads(s)['2']
××¨× ×¦×§××

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

编辑 – 解决方案(?):

我会尝试总结Martijn Pieters的评论和答案:
(编辑:@ Sebastian的评论之后的第二个想法,大约一年之后)

  1. might be no json.dumps中的内置解决方案。
  2. 我必须将所有字符串转换为UTF8 Unicode对象,然后才被JSON编辑。
     i’ll use Mark’s function that converts strings recuresively in a nested object
  3.  the example I gave depends too much on my computer & IDE environment, and doesn’t run the same on all computers.

谢谢大家 :)

回答:

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

>>> json_string = json.dumps(u"ברי צקלה", ensure_ascii=False).encode('utf8')
>>> json_string
'"\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94"'
>>> print json_string
"ברי צקלה"

如果您正在将文件写入文件,则可以使用io.open()而不是open()生成一个在编写Unicode时为其编码的文件对象,然后使用json.dump()写入该文件:

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

在Python 3中,内置的open()io.open()的别名。请注意,bug in the json module ensure_ascii=False标志可以生成unicodestr个对象的mix。 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: '\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94', 2: u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4'}

>>> s=json.dumps(d, ensure_ascii=False, encoding='utf8')
>>> s
u'{"1": "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4", "2": "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"}'
>>> json.loads(s)['1']
u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4'
>>> json.loads(s)['2']
u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4'
>>> print json.loads(s)['1']
ברי צקלה
>>> print json.loads(s)['2']
ברי צקלה

请注意,你的第二个样本是有效的Unicode;你给它的UTF-8字节作为一个unicode字面值,这将never工作:

>>> s = u'\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94'
>>> print s
××¨× ×¦×§××
>>> print s.encode('latin1').decode('utf8')
ברי צקלה

只有当我将该字符串编码为拉丁文1(其Unicode码编码点映射到一个字节),然后解码为UTF-8,您会看到预期的输出。这与JSON无关,所有与您使用错误的输入有关。结果称为Mojibake
如果您从字符串文字中获得Unicode值,则使用错误的编解码器进行解码。可能是您的终端配置错误,或者您的文本编辑器使用不同于使用Python读取文件的编解码器来保存源代码。或者您从应用错误编解码器的库中采购它。 这与JSON库无关

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Saving utf-8 texts in json.dumps as UTF8, not as \u escape sequence

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

29 + = 37