调试接口时看到返回的是 \u4f60\u597d,日志里冒出 你,配置文件里出现 你——这些都是「你」这个字的不同编码写法。Unicode 转义是国际化和字符处理的通用语言,认识它的几种形态,排查乱码问题就不再抓瞎。
Unicode 给世界上每个字符分配一个唯一编号(码点)。「你」的码点是 U+4F60,「好」是 U+597D。编号本身是数字,但不同语言和场景用不同的「写法」来表达它:
| 写法 | 例子 | 常见出现地 |
|---|---|---|
| \u 转义 | \u4f60 | JavaScript、Java、JSON 字符串 |
| 十进制 HTML 实体 | 你 | HTML 源码、XML |
| 十六进制 HTML 实体 | 你 | HTML 源码、部分模板引擎 |
| U+ 记法 | U+4F60 | Unicode 官方文档、字符百科 |
验证一下:20320 的十六进制正是 4F60,所以三种写法指向同一个字。看到任何一种形态,本质都是在读这张「身份证号」。
很多后端框架在序列化 JSON 时默认把非 ASCII 字符转成 \uXXXX,好处是传输管道对纯 ASCII 绝对安全,坏处是人不能直接读。这不是乱码,数据本身是完好的——把它转回中文即可。而真正的乱码(比如「ä½ å¥½」这种)是编码方式用错了,两者要区分开。
排查乱码的三步法:
\u 或 &# 开头,只是编码了,转换即还原;日常最高频的两个方向:
\u4f60\u597d\uff0c\u4e16\u754c 粘进转换工具,得到「你好,世界」——读接口返回、看国际化配置文件必备;\uXXXX——写国际化资源文件、构造安全的字符串字面量、排查字符边界问题时用。注意代理对:表情符号等超出基本平面的字符(码点大于 U+FFFF)在 \u 写法里由两个转义成对表示,例如 😀 是 \ud83d\ude00。转换工具会自动处理这种成对关系,手工拆开单独转就会出错。
问:UTF-8 和 Unicode 是一回事吗?
不是。Unicode 是字符编号表,UTF-8 是把编号存成字节的一种方式。同一个「你」字,Unicode 码点是 U+4F60,UTF-8 编码后是三个字节 E4 BD A0。
问:为什么有些字符转义后长度不一样?
基本平面字符(常用汉字都在内)固定 4 位十六进制;增补平面字符需要代理对,长度翻倍。这是历史设计,不是错误。
问:HTML 里的实体和 \u 转义能混用吗?
在各自语境里都能还原成同一个字符,但语法不通用:JSON 里写 你 不会还原,HTML 里写 \u4f60 也不会还原,要在对的场景用对的写法。
\u4exx 到 \u9fxx 区间的转义,基本就是中文;\uXXXX 是唯一合法的非 ASCII 表达,所以接口文档见到它别慌,是标准行为。把 \u4f60 当成「你」的第二种写法,Unicode 这件事就通了。下次遇到转义串,直接贴进工具里一秒还原。