参考资料:为什么我的“特殊”Unicode 字符使用 json_encode 编码很奇怪?

Reference: Why are my "special" Unicode characters encoded weird using json_encode?

提问人:deceze 提问时间:3/30/2014 更新时间:8/25/2014 访问量:3928

问:

当使用“特殊”Unicode字符时,当编码为JSON时,它们会变成奇怪的垃圾:

php > echo json_encode(['foo' => '馬']);
{"foo":"\u99ac"}

为什么?我的编码有问题吗?

(这是一个参考问题,可以一劳永逸地澄清这个话题,因为它一次又一次地出现。

php unicode utf-8 json

评论


答:

29赞 deceze 3/30/2014 #1

首先:这里没有错。这就是 JSON 中对字符进行编码的方式。它属于官方标准。它基于 Javascript ECMAScript 中字符串文字的形成方式(第 7.8.4 节 “字符串文字”),并描述如下:

任何代码点都可以表示为十六进制数。该数字的含义由 ISO/IEC 10646 确定。如果代码点位于基本多语言平面(U+0000 到 U+FFFF)中,则可以表示为六个字符的序列:反向实线,后跟小写字母 u,后跟对码位进行编码的四个十六进制数字。[...]因此,例如,仅包含单个反向实线字符的字符串可以表示为“\u005C”。

简而言之:任何字符都可以编码为 ,其中是字符的 Unicode 码位(或 UTF-16 代理项对的一半码位,对于 BMP 之外的字符)。\u........

"馬"
"\u99ac"

这两个字符串文本表示完全相同的字符,它们是绝对等效的。当这些字符串文字由兼容的 JSON 解析器解析时,它们都将生成字符串“馬”。它们看起来不一样,但它们在 JSON 数据编码格式中的含义相同。

PHP 的json_encode最好使用转义序列对非 ASCII 字符进行编码。从技术上讲,它不一定是,但它确实如此。结果是完全有效的。如果您希望在 JSON 中使用文字字符而不是转义序列,您可以在 PHP 5.4 或更高版本中设置标志:\u....JSON_UNESCAPED_UNICODE

php > echo json_encode(['foo' => '馬'], JSON_UNESCAPED_UNICODE);
{"foo":"馬"}

需要强调的是:这只是一种偏好,没有必要以任何方式在 JSON 中传输“Unicode 字符”。

评论

5赞 jfs 3/31/2014
注意:JSON 是 ECMA 404,而不是 ECMA 262 (JavaScript)。此外,非 BMP Unicode 代码点可以表示为 UTF-16 代理项对,例如,跳动的心脏 -- U+1F493 表示为 json 字符串。"\ud83d\udc93"
1赞 Mathias Bynens 3/31/2014
+1.在 JavaScript 中所有可能的转义序列中,JSON 只支持一些单字符的转义序列,\n 和所谓的 Unicode 转义序列
2赞 Joe Hildebrand 6/28/2014
如果您使用的是 ECMAscript 以外的语言的 JSON,则更好的参考可能是 RFC 7159 (tools.ietf.org/html/rfc7159),它与 ECMA-404 保持一致。
0赞 Your Common Sense 7/25/2022
你是编码精灵,我可以把你召唤到这个问题中吗?stackoverflow.com/q/73099438/285587我想知道为什么\u00xx需要额外的解码。