必须用StringBuffer+Writer配对并调用SetIndent()才能美化JSON输出,Stringify()默认无缩进且忽略缩进设置;Accept()允许自定义格式化,而Stringify()使用默认Writer。

为什么StringBuffer和Writer必须配对使用
直接调用document.Stringify()默认不带缩进,想美化输出必须走StringBuffer + Writer这一层。RapidJSON的美化逻辑不在Document本身,而是在序列化时由Writer控制——它需要一个缓冲区来累积格式化后的字符,StringBuffer就是这个角色。
常见错误是只创建StringBuffer但没传给Writer,或者误用GenericStringBuffer却传了错误模板参数(比如漏掉UTF8),结果编译报错或输出乱码。
-
StringBuffer类型必须与Writer模板参数一致:通常用StringBuffer(即GenericStringBuffer<utf8>>)</utf8>) -
Writer构造时必须传入StringBuffer引用,不能传值或指针 - 写完后用
buffer.GetString()取结果,不是buffer.GetBuffer()
怎么用Writer开启缩进和换行
关键在Writer构造后调用SetIndent()——它接受两个参数:缩进字符(如' '或'\t')和每级缩进长度(如2或4)。不调用这个函数,即使走Writer路径也还是紧凑格式。
注意:SetIndent()必须在任何StartObject()/Key()等写入操作之前调用,否则无效。换行符自动由Writer注入,无需手动加\n。
立即学习“C++免费学习笔记(深入)”;
- 推荐组合:
writer.SetIndent(' ', 2)—— 空格缩进,每级2个空格 - 如果用制表符:
writer.SetIndent('\t', 1),注意Windows控制台可能显示异常 - 调用
Stringify()会忽略SetIndent()设置,必须用Accept()把Document喂给Writer
Accept()和Stringify()的区别在哪
Stringify()是便捷封装,底层其实也用了Writer,但它用的是默认无缩进的Writer实例;而Accept()让你完全掌控Writer行为,包括缩进、浮点数精度、Unicode转义等。想美化,只能选Accept()。
典型误用是写了SetIndent()却仍调用doc.Stringify(buffer),结果缩进没生效——因为Stringify()内部新建了一个未配置的Writer。
- 正确链路:
StringBuffer buffer; Writer writer(buffer); writer.SetIndent(' ', 2); doc.Accept(writer); const char* json = buffer.GetString(); -
Accept()返回bool,失败通常意味着Document结构非法(比如key不是string) - 如果
Document含中文,确保源字符串是UTF-8编码,否则GetString()输出可能乱码
性能和内存要注意什么
StringBuffer内部用std::string或动态分配内存,默认增长策略可能触发多次重分配。大JSON生成时,可预先用Reserve()估算容量(比如buffer.Reserve(4096)),避免频繁拷贝。
另外,Writer不是线程安全的,多线程场景下每个线程必须有自己的StringBuffer和Writer实例。
- 不要复用
StringBuffer:每次生成前调用buffer.Clear(),而不是新建对象(小开销) - 调试时可用
buffer.GetSize()检查生成长度,避免意外截断 - Release模式下
Writer性能接近紧凑格式,美化几乎不额外耗时
缩进逻辑在Writer写入时实时计算,没有“后处理美化”这种操作——这意味着你没法对已生成的紧凑JSON再加工,必须从Document开始走Accept()流程。


















