nlohmann/json 序列化需手动定义 to_json 函数,支持嵌套与容器,私有/const 成员需友元或 getter,utf-8 编码须确保输入合法,性能优化应避免重复构造及跨模块 odr 问题。

用 nlohmann/json 库序列化 C++ 对象最直接
没有标准库支持,必须依赖第三方 JSON 库;nlohmann/json 是目前最主流的选择,头文件即用、语法贴近直觉,且对自定义类型支持清晰。
关键前提是:你的类必须显式定义如何映射到 JSON,不能靠自动反射(C++ 没运行时类型信息)。
- 在类内声明
to_json函数(非成员、非模板),接受json&和 const 引用对象 - 或在命名空间中为该类重载
to_json,注意需与类在同一命名空间或被 ADL 找到 - 字段名必须手动写死字符串,不支持宏自动生成字段名(除非额外引入 codegen 工具)
- 嵌套对象、
std::vector、std::map等容器可直接赋值,库会递归处理
struct Person {
std::string name;
int age;
};
<p>void to_json(nlohmann::json& j, const Person& p) {
j = nlohmann::json{{"name", p.name}, {"age", p.age}};
}</p><p>// 使用
Person p{"Alice", 30};
std::string s = nlohmann::json(p).dump(); // → {"name":"Alice","age":30}
</p>
遇到 const 成员或私有字段怎么办
编译失败常见于字段不可访问或不可拷贝——to_json 函数体内访问私有成员时,需将其声明为友元,或改用 public getter。
基于三引擎设计,从微信文章、新闻和博客网页提取干净内容,支持标题作者日期元数据,多格式和批量处理。
- 加
friend void to_json(...)到类定义里是最简洁的解法 - 若字段是
const或只有constgetter,确保 getter 返回的是可序列化的类型(如const std::string&可直接用) - 避免在
to_json中调用可能抛异常的 getter,否则dump()可能中途失败 - 不要试图在
to_json里修改对象状态——它应是纯读取操作
中文乱码或特殊字符出错
nlohmann/json 默认输出 UTF-8,但如果你看到 或空字符串,大概率是输入字符串本身不是合法 UTF-8(比如 GBK 编码的 char* 被误当 UTF-8 解析)。
- 确认源字符串变量确实是 UTF-8 编码;Windows 控制台默认 ANSI,
std::string从 cin 读入时可能已损坏 - 不用手动转义,库会自动处理引号、反斜杠、控制字符;但非法字节序列会导致
dump()抛nlohmann::json::type_error - 调试时可用
j.dump(2)加缩进,方便肉眼检查结构,但不影响编码逻辑 - 若需严格控制输出格式(如禁止 Unicode 转义 \uXXXX),用
json::dump_options配置,但非常规需求
性能敏感场景要注意什么
每次调用 json(obj).dump() 都触发完整构造 + 序列化,临时对象多、内存分配频繁。
- 避免在 tight loop 里反复序列化同一对象;可缓存
nlohmann::json实例(只要对象不变) -
dump()默认分配新 string,如需写入已有 buffer,用dump(std::string&)重载减少拷贝 - 深度嵌套或超大数组时,栈空间可能不足;可设编译宏
NLOHMANN_JSON_DISABLE_EXCEPTIONS关异常,改用返回错误码风格(需自行封装) - 不推荐为性能过早优化——先测再调;99% 场景下,语义清晰比省几十纳秒更重要
真正麻烦的是跨模块共享序列化逻辑:一旦类定义在 A 库,to_json 实现放在 B 库,链接期可能 ODR-violation。最稳的方式是把 to_json 定义和类声明放在一起,或至少确保只在一个 TU 中实例化。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










