rapidjson写入文件前必须先序列化成字符串;需用StringBuffer+Writer转为字符串再手动写入,直接写Document会导致空文件或乱码。

rapidjson 写入文件前必须先序列化成字符串
rapidjson 本身不提供直接写文件的 API,Document 或 Value 对象不能直接丢给 fopen 或 std::ofstream。你得先用 StringBuffer + Writer 把它转成字符串,再手动写入文件——跳过这步,只会得到空文件或乱码。
- 常见错误:直接对
Document调用operator 或试图 <code>write(fd, &doc, sizeof(doc)),结果是二进制内存布局,不是 JSON 文本 - 正确路径:创建
StringBuffer→ 构造Writer<StringBuffer>→Accept()序列化 → 用GetString()拿 C-style 字符串 → 写入文件 - 注意
StringBuffer的编码默认是 UTF-8,如果目标文件需 UTF-16(如 Windows 记事本默认),得自己加 BOM 并用宽字符流,rapidjson 不处理这个
用 Writer 写入时别漏掉 PrettyWriter(如果要格式化)
默认 Writer 输出的是紧凑 JSON(无换行、无缩进),看起来像一行密文。调试时很难看,但很多人卡在“生成了却读不懂”,其实只是没切到美化模式。
- 紧凑输出用
Writer<StringBuffer>,性能略高,适合日志或网络传输 - 想带缩进和换行,得用
PrettyWriter<StringBuffer>,它多一个SetIndent()方法,比如writer.SetIndent(' ', 2) -
PrettyWriter会多分配一点内存、稍慢一点,但开发期值得;上线后可按需切回普通Writer - 别试图在
Writer上调SetIndent——它没这个方法,编译报错
文件写入要用 std::ofstream::binary 模式(尤其含中文时)
Windows 下用文本模式(默认)写 UTF-8 字符串,可能被 \n → \r\n 自动替换,导致 JSON 里出现意外的 \r,解析失败;Linux/macOS 虽不替换,但显式声明 binary 更安全。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 正确写法:
std::ofstream file("out.json", std::ios::out | std::ios::binary) - 错误写法:
std::ofstream file("out.json")(隐式 text 模式) - 如果 JSON 含中文,且用
StringBuffer.GetString()得到的是 UTF-8 字节流,binary 模式确保字节原样落盘 - 别用 C 风格
fopen(..., "w")—— 在 Windows 上它也是文本模式,同样有换行符干扰风险
Document 移动语义和生命周期容易出错
rapidjson 的 Document 和 Value 是非 RAII 设计,内部内存由自身管理,但你不小心把 Document 放在栈上又返回它的 GetString(),就可能踩到悬垂指针。
立即学习“C++免费学习笔记(深入)”;
- 典型坑:
return doc.GetString(),而doc是函数局部变量——GetString()返回的是内部缓冲区指针,函数返回后缓冲区已销毁 - 安全做法:确保
StringBuffer的生命周期 ≥ 字符串使用期;常见是把它和Writer放在同一作用域,或封装成临时对象 - 如果反复生成 JSON,别每次 new/delete
StringBuffer,复用它更高效(清空用Clear()) -
Document可以 move(std::move(doc)),但 move 后原对象进入 valid-but-unspecified 状态,不能再调GetString()
最常被忽略的是 StringBuffer 和 Document 的生命周期绑定关系——它们不是独立的,StringBuffer 依赖 Document 的内存池(除非你传自定义 allocator),所以 Document 销毁前,StringBuffer 不能先于它失效。


















