在日常数据处理中,你是否遇到过这样的字符串:\"text\": \"\\u597d\\u6d88\\u606f...\"?明明预期是中文文本,却充斥着大量反斜杠和 Unicode 编码,看起来像 “乱码”。其实这并非真正的乱码,而是多重转义叠加的产物。本文将带你理解转义的本质,找到用 JSON 解析器还原原始文本的核心解法。
先厘清:这不是 “乱码”,是多重转义
首先要明确一个认知:\"text\": \"\\u597d...\" 不是错误,而是字符串在 “跨系统传递” 过程中的 “规则妥协”。
转义的本质是:同一个字符在不同场景中承担 “普通字符” 和 “特殊功能字符” 两种角色。当需要表达字符的 “本义” 时,必须用反斜杠(``)标记,这就是转义。而多重转义,就是字符串经过多个 “需要转义的场景” 后,反斜杠和特殊字符被反复标记的结果。
以你遇到的字符串为例,核心转义来自两个场景:
场景 1:JSON 格式的 “边界转义”
JSON 语法中,双引号(")是字符串的 “边界符”(比如"text": "内容"中,前后的"用来标记字符串范围)。如果字符串内容本身包含",或需要写入 Unicode 编码(如\u597d表示 “好”),就必须用``转义:
- 双引号
"→ 转义为"(告诉 JSON 解析器:这是普通引号,不是边界); - 反斜杠`` → 转义为
\(告诉 JSON 解析器:这是普通反斜杠,不是转义符)。
比如 “text: "好消息"” 按 JSON 规则转义后,会变成:"text": "\u597d\u6d88\u606f"(中文 “好消息” 转为 Unicode 编码\u597d...,内部双引号转义为")。
场景 2:代码 / 日志系统的 “字面量转义”
当 JSON 字符串被嵌入到编程语言(如 Go、Java)的 “字符串字面量” 中,或写入日志系统时,会触发第二次转义。因为在代码中,本身也是 “转义符”—— 要表示 JSON 中的,必须再用一个``标记。
比如 JSON 中的"text": "\u597d...",嵌入到 Go 代码字符串中会变成:\"text\": "\u597d..."(JSON 中的"转义为",再被代码转义为\";JSON 中的\u转义为\u,再被代码转义为\\u)。
转义叠加全过程
用一张表清晰展示 “text: "好消息"” 如何变成你看到的字符串:
| 阶段 | 目标场景 | 原始内容 | 转义后结果 | 关键变化 |
|---|---|---|---|---|
| 1 | 人类可读文本 | text: "好消息" | - | 无转义,纯中文 |
| 2 | JSON 格式(1 次转义) | text: "好消息" | "text": "\u597d\u6d88\u606f" | 中文→Unicode,"→" |
| 3 | 代码字符串(2 次转义) | "text": "\u597d..." | \"text\": "\u597d..." | "→\",\u→\u |
| 4 | 日志存储(3 次转义,可选) | \"text\": "\u597d..." | \\\"text\\\": "\\\u597d..." | 再叠加一层``,\→\\ |
你遇到的\"text\": \"\\u597d...\",正是 “JSON 转义 + 代码转义” 后的二次转义结果 —— 是规则适配的必然,不是数据错误。
解决办法
逆袭还原回去即可,
json.Unmarshal([]byte(A), &B)