json.dumps将转义的Unicode编码为UTF-8

3

我来自这个旧的讨论,但是那个解决方案并没有太大帮助,因为我的原始数据已经以不同的方式编码:

我的原始数据已经被编码成Unicode,我需要输出为UTF-8。

data={"content":u"\u4f60\u597d"}

当我尝试转换为UTF时:

json.dumps(data, indent=1, ensure_ascii=False).encode("utf8")

我得到的输出是"content": "ä½ å¥½",期望的输出应该是"content": "你好"

我尝试了没有使用ensure_ascii=false,输出变成了未转义的"content": "\u4f60\u597d"

如何将之前的\u转义的json转换为UTF-8编码?


2
你正在使用错误的编解码器读取UTF-8数据。你UTF-8,但是将其解码为Latin-1或CP1252。换句话说,这不是Python的问题。 - Martijn Pieters
是的,我在 Python 3 REPL 中无法复现这个问题。 - David Grayson
2个回答

9

您有 UTF-8 JSON 数据:

>>> import json
>>> data = {'content': u'\u4f60\u597d'}
>>> json.dumps(data, indent=1, ensure_ascii=False)
u'{\n "content": "\u4f60\u597d"\n}'
>>> json.dumps(data, indent=1, ensure_ascii=False).encode('utf8')
'{\n "content": "\xe4\xbd\xa0\xe5\xa5\xbd"\n}'
>>> print json.dumps(data, indent=1, ensure_ascii=False).encode('utf8')
{
 "content": "你好"
}

我的终端恰好被配置为处理UTF-8,因此将UTF-8字节打印到我的终端会产生所需的输出。

但是,如果你的终端没有设置用于此类输出,则是你的终端显示“错误”的字符:

>>> print json.dumps(data, indent=1,  ensure_ascii=False).encode('utf8').decode('latin1')
{
 "content": "你好"
}

注意我如何将数据解码为Latin-1以故意误读UTF-8字节。
这不是Python的问题;这是你在使用任何工具读取这些字节时处理UTF-8字节的问题。

谢谢,是我的浏览器出了问题。我以为 ä½ å¥½ 是 Python 端的编码错误。结果证明这是输出本身 :) - Bonk
1
@Bonk:也许你需要设置一个正确的响应头?Content-Type: application/json就足够了(因为JSON标准规定UTF是默认值,带有BOM的开头可以区分UTF-8和UTF-16以及UTF-32),或者使用Content-Type: application/json; charset=utf8显式地包含字符集。如果没有Content-Type头或者将其设置为text/.. mimetype,则浏览器可能会默认为Latin-1。 - Martijn Pieters

4
在Python2中,它可以正常工作;然而在Python3中,print 的输出会像这样:
>>> b'{\n "content": "\xe4\xbd\xa0\xe5\xa5\xbd"\n}'

不要使用encode('utf8')

>>> print(json.dumps(data, indent=1, ensure_ascii=False))
{
 "content": "你好"
}

或者使用sys.stdout.buffer.write替代print:
>>> import sys
>>> import json
>>> data = {'content': u'\u4f60\u597d'}
>>> sys.stdout.buffer.write(json.dumps(data, indent=1, 
ensure_ascii=False).encode('utf8') + b'\n')
{
 "content": "你好"
}

请参见如何将UTF-8写入标准输出,无视控制台的编码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接