最省事直接的方法是使用 nlohmann/json 库:头文件即用,支持自然初始化如 json j = {{"name", "alice"}, {"age", 30}},序列化只需 std::ofstream("data.json")

用 nlohmann/json 库写 JSON 文件最省事
直接结论:C++ 标准库不带 JSON 支持,必须用第三方库;nlohmann/json 是目前最主流、语法最接近现代 C++ 的选择,头文件即用,无需编译依赖。
它把 JSON 当成一等公民来设计,比如支持 json j = {{"name", "Alice"}, {"age", 30}}; 这种自然初始化,序列化也只需一句 std::ofstream("data.json") 。
常见错误是手动拼接字符串(如 "{\"name\":\""+name+"\"}"),这极易出错——引号转义漏掉、中文乱码、嵌套结构崩塌,而且完全没法校验合法性。
- 确保项目能访问头文件:下载
json.hpp放入 include 路径,或用 vcpkg/conan 安装 - 别用旧版(如 3.x):v3.11.2+ 才默认启用 UTF-8 字符串安全处理,否则中文可能变
\uXXXX - 写文件前检查路径可写:Windows 下当前目录可能被权限限制,建议显式指定绝对路径或先
std::ofstream f("test.json"); if (!f) { /* 失败 */ }
std::ofstream 直接输出 JSON 时的编码和换行问题
JSON 是纯文本,但输出时容易踩两个坑:一是 Windows 换行符 \r\n 会被当成非法字符(虽然多数解析器容忍,但严格模式下报错);二是未声明 UTF-8 BOM 或编码设置,导致中文显示为乱码或 \uXXXX 序列。
nlohmann/json 默认以 UTF-8 输出,不加 BOM,这是正确做法(JSON RFC 明确要求 UTF-8 且不强制 BOM)。你只需确保终端/编辑器用 UTF-8 解码即可。
- 避免用
std::endl:它会插入\n并刷新缓冲区,影响性能;直接用"\n"即可 - 如果需要紧凑格式(无空格缩进),调用
j.dump(-1);默认j.dump()是带缩进的易读格式 - 不要对
std::ofstream手动 setlocale:C++ 流的 locale 不影响 UTF-8 字节流,设了反而可能干扰
写入失败却没报错?检查 std::ofstream 状态位
常见现象:std::ofstream f("out.json"); f 看似执行成功,但文件为空或根本没生成。根本原因不是 JSON 库的问题,而是文件流打开失败后,<code>operator 仍会静默执行(只是不写入)。
C++ 流默认关闭异常模式,错误全靠状态位(failbit/badbit)指示,不主动检查就等于“假装成功”。
- 务必在写完后检查:if (f.fail()) { /* 处理失败 */ },或者更早检查打开是否成功:
if (!f.is_open()) - 路径含中文或特殊字符时,Windows 下需用
std::filesystem::path构造并转宽字符,或改用 UTF-8 路径(需编译器支持,如 MSVC 19.32+ 加/utf-8) - Linux/macOS 下注意父目录是否存在:
std::ofstream不会自动创建多级目录,mkdir -p得自己调用std::filesystem::create_directories
需要高性能或嵌入式环境?别硬上 nlohmann/json
它的优势是开发效率,劣势是运行时开销:每个 key 查找走哈希表,对象构建涉及多次堆分配,小资源设备或高频写入场景(如每毫秒写一次传感器数据)会明显卡顿。
这时候应考虑轻量替代方案:
- 用
rapidjson的Writer模式:纯栈分配 + SAX 风格写入,速度更快,但 API 更底层,得手动控制StartObject()/String()/EndObject()流程 - 极简场景下,手写模板函数生成固定结构 JSON(如
fmt::format(R"({{"ts":{}, "val":{}}})", ts, val)),前提是字段数少、无动态嵌套、且能保证值本身不含双引号或控制字符 - 千万别用
printf类接口拼接:C 风格格式化无法自动转义字符串中的"或\n,一写就崩
真正难的从来不是“怎么写出 JSON”,而是“怎么让 JSON 写得稳、读得准、改得不破”。路径权限、编码一致性、错误反馈链,这些地方漏一个,调试时间翻倍。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











