【问题标题】:Parsing JSON string with \u escapes使用 \u 转义解析 JSON 字符串
【发布时间】:2017-06-12 22:28:16
【问题描述】:

我有一个 Python 服务,其端点将数据传递给另一个服务,获取结果并将其传递给请求者。表单中有一个 message 归档,如果我输入一个 Unicode 字符 - 比如说“微笑的眼睛笑脸” (U+1F601) - 我在请求表单对象中看到以下内容

ImmutableMultiDict([('message', u'\U0001f601'),...

当我得到其他服务的响应时,我有这个

{..., u'message': u'\xf0\x9f\x98\x81',...}

然后使用 json.dumps 将其 JSON 化为

{..."message": "\u00f0\u009f\u0098\u0081"...}

最后,在客户端,消息字符串被解析成

ð

(如果我没记错的话,那个字符的 Unicode 代码是\u00f0

那么它哪里出错了?看起来我有一个使用 utf8 十六进制转义从外部服务返回的字符串。我尝试使用 utf8 解码该字符串,但出现以下错误

return codecs.utf_8_decode(input, errors, True) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not inrange(128)

【问题讨论】:

  • u'\xf0\x9f\x98\x81'mojibake。所以第 1 步和第 2 步之间有问题。为了让任何人解决您的问题,他们必须有权访问complete code,当给定输入ImmutableMultiDict([('message', u'\U0001f601'),... 时产生{..., u'message': u'\xf0\x9f\x98\x81',...}
  • 信息还在。 :grin: 的 UTF-8 十六进制表示是 0xF0 0x9F 0x98 0x81,所以看起来是正确的。如果我在客户端执行decodeURIComponent(escape(message)),它会正确呈现。所以,我想最后我更感兴趣的是如何在 python 中正确处理这个问题。

标签: python json unicode encoding utf-8


【解决方案1】:

要正确处理此问题,您需要修复创建 u'\xf0\x9f\x98\x81' mojibake 的过程。如前所述,这些字节是正确的,但它们需要是纯字符串(在 Python 3 中是 bytes 字符串)而不是 Unicode 字符串。没有看到相关代码,我们无法提供更多细节。

但是,您可以通过将 mojibake 编码为拉丁语 1 来提取字节码,然后将这些字节解码为 UTF-8 以创建正确的 Unicode:

d = {u'message': u'\xf0\x9f\x98\x81'}
for k, v in d.items():
    # Extract bytes from mojibake Unicode
    b = v.encode('latin1')
    # Now decode the extracted bytes as UTF-8
    s = b.decode('UTF-8')
    print k, s

输出

message ?

或者更简洁的形式:

v = u'\xf0\x9f\x98\x81'
s = v.encode('latin1').decode('utf-8')
print(s)

这适用于 Python 2 和 3。


您应该认真考虑迁移到 Python 3,在该版本中 Unicode 处理更加明智,并且您不太可能产生此类混淆。

【讨论】:

  • 谢谢,我会试试的。不幸的是,我无法控制我得到的响应,但也许我可以做一些事情来以更适当的方式处理响应本身。
  • @alh84001 v.encode('latin1').decode('utf-8') 非常有效。那些.encode.decode 方法是用C 编码的,我认为它们经过了很好的优化,因为它们经常被使用,所以使用它们可能比使用decodeURIComponent 更快(它可能无论如何都会调用这些方法,之后它已经搞砸了)。
  • @alh84001 我想除了告诉“其他服务”他们的应用正在喷垃圾之外,您无能为力,让他们阅读 Ned Batchelder 的Pragmatic Unicode,并告诉他们获取他们一起行动并开始使用 Python 3。:)
  • 再次感谢。最后我发现我传递给服务的字典是POSTed 作为一组查询参数,而不是在请求正文中。我想那里还有一层额外的编码,因为当切换到另一个选项时,它可以正常工作。也感谢链接,我一定会看看:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-20
  • 2020-02-05
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多