JSON 工具箱

中文为什么变成 \u4e2d\u6587

结论:\u4e2d\u6587 是合法的 Unicode 转义,不是编码错误。真正的乱码是「测试」这种。分清两者,才知道该改序列化配置还是改文件编码。

入门约 3 分钟发布于 2026-10-30更新于 2026-10-30
中文 Unicode 转义与真正乱码的区别

结论:看到 \uXXXX 先当作正常转义,用 JSON.parse 试一次就能确认能否还原;要直接显示汉字就关掉序列化端的纯 ASCII 输出(如 ensure_ascii=False),只有传输通道不支持非 ASCII 时才保留转义。

因为它被转义了,不是坏了。

JSON.parse('"\\u4e2d\\u6587"')  // "中文"

\u4e2d 就是「中」,\u6587 是「文」。这两串字符是 JSON 字符串里的合法转义序列,解析器读到就会还原。功能上不会出错,只是在日志、抓包、代码评审里读起来很痛苦。

谁在转义

工具 默认行为 开关
Python json.dumps 转义(ensure_ascii=True) ensure_ascii=False
JavaScript JSON.stringify 不转义 无
Java Jackson 不转义 可选开启
PHP json_encode 不转义(5.4+) JSON_UNESCAPED_UNICODE
Go encoding/json 不转义 无

Python 是最高频的来源。它的默认值选择有历史原因:保证输出是纯 ASCII,任何环境都能安全传输。代价就是中文全变转义串。

转义 vs 乱码,先分清

这两种现象经常被混为一谈,但成因完全不同:

转义:\u4e2d\u6587,形如 \uXXXX,每个汉字六个字符。原因:序列化配置。 乱码:测试、涓枃,形如一堆西欧字母或生僻字。原因:字节按 UTF-8 写入,却按 Latin-1 或 GBK 读取。

判断方法很简单:把文本复制到浏览器控制台执行 JSON.parse('"粘贴内容"')。能还原成正常中文就是转义,还原不出来或者直接报错,就是编码问题。

乱码的修法完全不同——要统一读写两端的编码,而不是改转义开关。

想直接看到汉字

Python:

json.dumps(data, ensure_ascii=False)

PHP:

json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)

改完记得确认下游没问题:有些老系统真的依赖纯 ASCII 传输,尤其是走短信、邮件、旧版网关的场景。

什么时候该保留转义

  • 传输通道对非 ASCII 不友好(旧版 HTTP 头、部分短信网关)
  • 需要把 JSON 嵌进另一层 JSON 字符串里,转义能少一层引号冲突
  • 日志系统按字节截断,多字节字符被切断会产生非法序列

除此之外,可读性优先,关掉转义。

常见问题

为什么 Python 默认把中文转成 \uXXXX?

因为 ensure_ascii=True 是默认值,保证输出是纯 ASCII,任何环境都能安全传输。代价是每个非 ASCII 字符变成六个字符。

要不要关闭 ensure_ascii?

可读性优先时关掉,改完再确认下游:旧版 HTTP 头、部分短信网关、按字节截断的日志系统仍可能依赖纯 ASCII。

传输通道不支持非 ASCII 时是否要保留转义?

要。把 JSON 嵌进另一层 JSON 字符串,或走对非 ASCII 不友好的通道时,转义能减少引号冲突,也能避免多字节字符被截断。

相关工具

延伸阅读