使用 json 负载时表情符号的 Unicode 解码不匹配
Unicode decode mismatch on emojis when using json loads
我有一个 utf-8 编码对象列表,例如:
test = [b'{"abc\xf0\x9f\x94\xa5\xf0\x9f\x91\xbd\xf0\x9f\xa7\x83": 123}',
b'{"abc\xf0\x9f\xa7\x83": 234}']
解码如下:
result = list(map(lambda x: json.loads(x.decode('utf-8','ignore')),test))
我注意到某些表情符号未按预期转换,如下所示:
[{'abc\U0001f9c3': 123}, {'abc\U0001f9c3': 234}]
然而,当我解码单个字符串时,我得到了预期的输出:
print(b"abc\xf0\x9f\x94\xa5\xf0\x9f\x91\xbd\xf0\x9f\xa7\x83".decode('utf-8'))
abc
我不确定为什么使用 json.loads 的第一种方法会产生意外的输出。有人可以提供任何指示吗?
在 json.loads()
之后您正在打印列表。列表使用引用 Unicode 表的字符串 (repr()
) 的调试表示来确定代码点是否可打印。如果未知,您会在列表显示中获得转义码。 print
一个字符串直接查看没有转义码的字符串(str()
)的“user-friendly”表示。
U+1F9C3 BEVERAGE BOX 已添加到 Unicode 12.0. Python 3.7 uses Unicode 11.0 定义中,这就是为什么您会看到带有转义码的原因。 Python 3.8 使用 Unicode 12.1,更新后的表格表明该字符可打印。如果您的终端支持该字符并且使用了适当的字体,它将显示。
例如,我使用的是支持 Unicode 13.0 的 Python 3.10。 U+1F978 在 Unicode 13.0 but U+1F979 was added in Unicode 14.0 中定义。您的浏览器可能会或可能不会显示实际的表情符号,具体取决于浏览器的 Unicode 支持和使用的字体(Chrome 99 没有)。如果不是,则打印替换字符。这仍然证明了字符串的 repr()
显示与 print
:
使用的 str()
之间的区别
>>> s = '\U0001f978\U0001f979'
>>> s # The REPL shows the repr (debug) representation
'\U0001f979'
>>> print(repr(s)) # forcing print to use the repr as well.
'\U0001f979'
>>> [s] # repr() is also used for list content.
['\U0001f979']
>>> print(s) # no escape codes here.
>>> print(ascii(s)) # forcing all non-ASCII to escape codes
'\U0001f978\U0001f979'
我有一个 utf-8 编码对象列表,例如:
test = [b'{"abc\xf0\x9f\x94\xa5\xf0\x9f\x91\xbd\xf0\x9f\xa7\x83": 123}',
b'{"abc\xf0\x9f\xa7\x83": 234}']
解码如下:
result = list(map(lambda x: json.loads(x.decode('utf-8','ignore')),test))
我注意到某些表情符号未按预期转换,如下所示:
[{'abc\U0001f9c3': 123}, {'abc\U0001f9c3': 234}]
然而,当我解码单个字符串时,我得到了预期的输出:
print(b"abc\xf0\x9f\x94\xa5\xf0\x9f\x91\xbd\xf0\x9f\xa7\x83".decode('utf-8'))
abc
我不确定为什么使用 json.loads 的第一种方法会产生意外的输出。有人可以提供任何指示吗?
在 json.loads()
之后您正在打印列表。列表使用引用 Unicode 表的字符串 (repr()
) 的调试表示来确定代码点是否可打印。如果未知,您会在列表显示中获得转义码。 print
一个字符串直接查看没有转义码的字符串(str()
)的“user-friendly”表示。
U+1F9C3 BEVERAGE BOX 已添加到 Unicode 12.0. Python 3.7 uses Unicode 11.0 定义中,这就是为什么您会看到带有转义码的原因。 Python 3.8 使用 Unicode 12.1,更新后的表格表明该字符可打印。如果您的终端支持该字符并且使用了适当的字体,它将显示。
例如,我使用的是支持 Unicode 13.0 的 Python 3.10。 U+1F978 在 Unicode 13.0 but U+1F979 was added in Unicode 14.0 中定义。您的浏览器可能会或可能不会显示实际的表情符号,具体取决于浏览器的 Unicode 支持和使用的字体(Chrome 99 没有)。如果不是,则打印替换字符。这仍然证明了字符串的 repr()
显示与 print
:
str()
之间的区别
>>> s = '\U0001f978\U0001f979'
>>> s # The REPL shows the repr (debug) representation
'\U0001f979'
>>> print(repr(s)) # forcing print to use the repr as well.
'\U0001f979'
>>> [s] # repr() is also used for list content.
['\U0001f979']
>>> print(s) # no escape codes here.
>>> print(ascii(s)) # forcing all non-ASCII to escape codes
'\U0001f978\U0001f979'