JSON字符串转义的核心规则是严格按RFC 8259处理6种必须转义情形:双引号、反斜杠、退格、换页、换行、回车、制表符,以及ASCII控制字符(0x00–0x1F)须转为u00XX,非ASCII Unicode可保留UTF-8字节序列。

JSON字符串转义的核心规则是什么
JSON规范要求字符串中必须转义特定字符,否则解析会失败。最常踩的坑是只处理双引号和反斜杠,却漏掉换行符、制表符、ASCII控制字符(U+0000–U+001F)以及非ASCII Unicode 字符——这些在 JSON 中要么必须用 uXXXX 表示,要么直接保留(前提是编码为 UTF-8 且不包含非法控制符)。
C++ 标准库不提供现成的 JSON 转义函数,所以得自己实现或借助轻量工具。关键不是“把所有特殊字符都加反斜杠”,而是严格按 RFC 8259 列出的 6 种必须转义情形处理:
-
"→" -
→ -
→ -
→ -
→ -
→ -
→ - ASCII 控制字符(0x00–0x1F,不含上面已列的)→
u00XX - 非 ASCII Unicode 码点(≥0x80)→ 保持原 UTF-8 字节序列,不强制转成
uXXXX(除非你目标环境只支持 ASCII JSON)
手动实现转义函数要注意哪些边界
用 std::string 处理时,不能简单遍历 char,因为 UTF-8 多字节字符会被拆开。正确做法是:先确保输入是合法 UTF-8,再按 Unicode 码点解码(或保守地只扫描单字节),对每个码点判断是否需转义。
更实用的做法是「白名单式扫描」:只检查 ASCII 范围内需转义的字符(0x00–0x1F 和 "、),其余字节原样保留——这对 UTF-8 安全,因为多字节序列首字节总是 ≥0xC0,不会被误判。
立即学习“C++免费学习笔记(深入)”;
std::string json_escape(const std::string& s) {
std::string out;
out.reserve(s.size() * 2); // 预估上限
for (unsigned char c : s) {
switch (c) {
case '"': out += "\""; break;
case '\': out += "\\"; break;
case '': out += "\b"; break;
case '': out += "\f"; break;
case '
': out += "\n"; break;
case '
': out += "\r"; break;
case ' ': out += "\t"; break;
default:
if (c <= 0x1F) {
out += fmt::format("\u{:04x}", c); // 需要 fmt 或 sprintf
} else {
out += c;
}
}
}
return out;
}
注意:fmt::format 不是标准库,若不用第三方,可用 sprintf + std::array<char, 8> 拼接;std::ostringstream 效率较低,不适合高频调用。
为什么不要用 std::regex 或 std::replace 做 JSON 转义
正则引擎默认按字节匹配,无法识别 UTF-8 边界,std::regex_replace(R"(")", R"(")) 看似可行,但遇到 "é"(é 的 UTF-8 编码)时,可能错误匹配中间字节,导致损坏。
std::replace 更危险:它只能做单字符替换,无法处理
→
这种“一字节变两字节”的情况,会覆盖后续内存或截断。
常见错误写法:
-
std::replace(s.begin(), s.end(), '"', '"')—— 这只是把"换成另一个",没加反斜杠 -
s.replace(pos, 1, "\"")循环调用 —— 每次修改都会使后续pos失效,极易越界或漏转
使用 nlohmann/json 等库时如何避免二次转义
如果你已经用 nlohmann::json 构建对象,直接赋值 obj["key"] = my_string 即可,它内部自动完成转义。此时绝不要先调用自定义转义函数再塞进去,否则会出现 \" 这类双重转义。
同样,从 nlohmann::json 取值时,obj["key"].get<:string>()</:string> 返回的是原始未转义字符串,无需、也不应再“反转义”。
容易忽略的一点:若字符串来自用户输入或文件读取,且编码不确定(比如可能是 GBK),必须先转换为 UTF-8 再喂给 JSON 库——否则库仍会按字节处理,导致乱码或解析失败。
转义本身不难,难的是明确输入编码、清楚目标 JSON 解析器的容忍度,以及别在序列化/反序列化链路上重复操作。


















