nlohmann/json 是 c++ 中序列化嵌套对象到文件最稳方案:直接构造 json 对象组合嵌套结构,写入前用 std::ofstream::imbue(std::locale("")) 防中文乱码,调用 j.dump(2) 保证可读缩进。

用 nlohmann/json 序列化嵌套对象到文件最稳
直接上结论:C++ 没原生 JSON 支持,nlohmann/json 是目前最省心、语法最接近现代 C++ 的选择。它把嵌套结构当普通对象操作,不用手写递归或拼字符串。
常见错误是硬套 std::map 或 std::vector 去模拟 JSON,结果类型擦除后写入时崩溃,或者中文字段乱码——这通常是因为没设 UTF-8 编码写入。
- 必须用
json::parse()或直接构造json对象,别用裸指针或自定义结构体强转 - 写入文件前,用
std::ofstream打开时加std::ios::out | std::ios::binary,并调用file.imbue(std::locale(""));防止 Windows 下中文变问号 - 嵌套太深(比如 10 层以上)且含大量重复 key 时,考虑用
json::object_t显式声明,避免隐式转换开销
json 对象怎么表示多层嵌套结构
不是靠 struct 套 struct,而是靠 json 类型的自然组合:对象里放对象、数组里放对象、对象里放数组。它会自动处理引号、转义、逗号分隔。
比如一个带用户列表、每个用户有地址和订单数组的结构,直接这样写:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
json j;
j["users"] = json::array();
j["users"].push_back({
{"name", "张三"},
{"address", {{"city", "北京"}, {"zip", "100000"}}},
{"orders", json::array({{{"id", 101}, {"items", json::array({"apple", "banana"})}}})}
});
- 注意:用
{}初始化时,内部必须是键值对(std::string,int,double,json等),不能混入const char*(会变成指针地址) - 数组元素如果本身是对象,必须用
{{...}}两层大括号,否则编译失败 - 字段名必须是
std::string或字面量字符串("key"),不能是char[]变量
写入文件时中文乱码或格式难读怎么办
根本原因有两个:一是文件流没设本地化,二是默认序列化不带缩进。这不是 bug,是设计选择——紧凑输出适合网络传输,但调试时确实反人类。
- 解决乱码:在
std::ofstream构造后立刻调用file.imbue(std::locale(""));(Linux/macOS 有效);Windows 下建议用std::wofstream+std::codecvt_utf8<wchar_t></wchar_t>,但更简单的是统一用 UTF-8 编码的std::ofstream并确保编辑器以 UTF-8 打开 - 解决可读性:用
j.dump(2)而不是j.dump(),第二个参数是缩进空格数;如果要兼容旧系统(如某些嵌入式 JSON 解析器),避免用dump(4)这种大缩进 - 别用
std::cout 直接输出到终端调试,某些终端对 Unicode 控制字符支持不好,优先写入临时文件再查看
结构体自动转 json 的坑在哪
nlohmann/json 支持 ADL(Argument-Dependent Lookup)方式为自定义类型添加序列化逻辑,但很多人卡在宏展开和命名空间上。
典型错误是把 NLOHMANN_DEFINE_TYPE_INTRUSIVE 写在类定义外、或写在匿名命名空间里,导致编译器找不到 to_json 函数。
- 必须把宏写在和结构体**同一命名空间内**,且在结构体定义之后、使用之前
- 字段名必须和 JSON key 完全一致,大小写敏感;如果结构体字段叫
m_name,但想序列化成"name",得用NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT配合重命名 - 含
std::unique_ptr或裸指针的成员,不会自动解引用,必须手动在to_json里处理,否则序列化出来是空对象或地址值
嵌套越深,手动控制序列化逻辑越必要。靠自动推导容易漏字段,尤其当结构体里混了 std::optional、std::variant 这类类型时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










