正确做法是用二进制模式读取json文件并确保utf-8编码:std::ifstream f("config.json", std::ios::binary);nlohmann::json仅支持utf-8,不处理bom、gbk或注释。

读取含转义字符的 JSON 文件时,fstream 默认不处理换行/制表符,必须用二进制模式或确保源文件编码一致
Windows 下用记事本保存的 JSON 文件若含中文和
、 ,直接用 std::ifstream 文本模式读取可能触发 CR/LF 转换,导致 nlohmann::json::parse() 报 parse_error: invalid escape sequence。这不是 nlohmann 的 bug,而是流读取阶段就把原始字节破坏了。
正确做法是强制以二进制模式读取,再交给 nlohmann 解析:
std::ifstream f("config.json", std::ios::binary);
f.seekg(0, std::ios::end);
size_t size = f.tellg();
f.seekg(0);
std::vector<char> buffer(size);
f.read(buffer.data(), size);
nlohmann::json j = nlohmann::json::parse(buffer.begin(), buffer.end());</char>
- 不用
std::string+rdbuf(),因为rdbuf()在文本模式下会误吞 - 确保文件本身是 UTF-8 编码(无 BOM 最稳妥),nlohmann 只支持 UTF-8 输入
- 如果 JSON 里有
"path": "C:\Users\name"这类 Windows 路径,双反斜杠是合法 JSON 转义,nlohmann 会自动还原为单—— 不用额外 unescape
nlohmann::json::parse() 对 uXXXX 和 \ 的处理是标准且严格的,但错误常来自编辑器保存行为
比如你写 "msg": "你好
世界",编辑器若以 GBK 保存,nlohmann 会把两个汉字解析成非法 UTF-8 字节序列,报错位置显示在
前,容易误判为转义问题。
验证方式很简单:
std::string raw;
std::ifstream f("config.json", std::ios::binary);
std::getline(f, raw, ' '); // 一次性读完
std::cout
- nlohmann 本身不负责编码转换,只校验 UTF-8 合法性
-
u4f60这种 Unicode 转义会被正确转成 UTF-8 字节,无需手动 decode - JSON 标准禁止裸
(如"C: emp"),必须写成"C:\temp"或用正斜杠"C:/temp"
从文件加载后访问带反斜杠字段名或嵌套路径,要用 operator[] 链式调用而非硬编码字符串拼接
例如 JSON 内容为 {"user": {"name": "Alice", "metainfo": {"age": 30}}},其中 metainfo 是一个含反斜杠的键名。这时候不能写 j["user"]["metainfo"] —— C++ 字符串字面量里 i 是非法转义,编译不过。
正确写法只有两种:
- 用原始字符串字面量:
j["user"][R"(metainfo)" ]["age"] - 用
at()避免隐式转换:`j.at("user").at("meta\info").at("age")`(注意这里要写两个反斜杠,因为字符串字面量需转义)
如果字段名来自用户输入或配置,必须用 at() + try/catch,否则遇到不存在的 key 会抛 nlohmann::json::out_of_range。
大文件或频繁解析场景下,避免重复分配内存:复用 std::vector<char></char> 和 nlohmann::json 实例
每次解析都 new 一块 buffer、构造新 json 对象,在嵌入式或高频配置热更场景下会明显影响性能。nlohmann 支持 in-place 解析和对象复用:
static std::vector<char> s_buffer;
static nlohmann::json s_j;
<p>s_buffer.clear();
s_buffer.resize(file_size);
read_file_to_buffer("config.json", s_buffer.data(), file_size);
s_j = nlohmann::json::parse(s_buffer.begin(), s_buffer.end());</p></char>
- 不要用
json::parse(std::string),它会额外拷贝一次字符串 - 如果 JSON 结构固定,可配合
json::get<t>()</t>提前声明类型,减少运行时类型检查开销 - 注意
s_j是静态变量,多线程访问需加锁,或改用线程局部存储(thread_local)
最易被忽略的一点:nlohmann 不提供“跳过注释”功能,哪怕 JSON 文件里写了 // comment 或 /* ... */,解析必然失败 —— JSON 标准本来就不支持注释,别指望库帮你容错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











