json.dumps 使用什么编码?

What encoding is used by json.dumps?

当我在 Python 3.8 中使用 json.dumps 作为特殊字符时,它们被“转义”,例如:

>>> import json
>>> json.dumps({'Crêpes': 5})
'{"Cr\u00eapes": 5}'

这是什么编码?这是“转义编码”吗?为什么这种编码不是 encodings 模块的一部分? (另见 codecs,我想我都试过了。)

换句话说,如何使用 Python 编码、转义等将字符串 'Crêpes' 转换为字符串 'Cr\u00eapes'

它不是 Python 编码。这是 JSON 编码 Unicode 非 ASCII 字符的方式。它独立于 Python,并且在 Java 或 C 或 C++ 库中的使用完全相同。

规则是基本多语言平面中的非 ASCII 字符(即最大 16 位代码)编码为 \uxxxx,其中 xxxx 是 unicode 代码值。

这就解释了为什么ê写成\u00ea,因为它的unicode代码点是U+00EA

您可能对这是一个 JSON 字符串而不是直接 Python 字符串这一事实感到困惑。

Python 会将此字符串编码为 "Cr\u00eapes",其中 \u00ea 表示使用其十六进制代码点的单个 Unicode 字符。也就是说,在Python、len("\u00ea") == 1

JSON 需要相同的 类型的 编码,但是将 JSON 编码的值嵌入 Python 字符串需要您加倍反斜杠;所以在 Python 的表示中,这变成了 "Cr\u00eapes" ,其中你有一个文字反斜杠(必须用另一个反斜杠转义),两个文字零,一个文字 e 字符,和一个文字 a 字符。因此,len("\u00ea") == 6

如果文件中有 JSON,将其加载到 Python 中的绝对最简单的方法是使用 json.loads() 读取并将其解码为本机 Python 数据结构。

如果您需要单独解码十六进制序列,unicode-escape 函数对字节值执行此操作:

>>> b"Cr\u00eapes".decode('unicode-escape')
'Crêpes'

这有点巧合,只是因为 JSON 表示恰好与 Python unicode-escape 表示相同。你仍然需要一个 b'...' aka bytes 输入。 ("Crêpes".encode('unicode-escape') 产生一个 稍微 不同的表示。"Cr\u00eapes".encode('us-ascii') 产生一个 bytes 具有 Unicode 表示 b"Cr\u00eapes" 的字符串。)