FEATURED · 精选文章

RapidJSON 入门实战:C++ 高性能 JSON 解析与生成的 SAX/DOM 双风格 API 全解

发布时间 / 2026/9/14 12:11:14
来源 / 创域科博编辑部
栏目 / 资讯中心
RapidJSON 入门实战:C++ 高性能 JSON 解析与生成的 SAX/DOM 双风格 API 全解 RapidJSON 入门实战C 高性能 JSON 解析与生成的 SAX/DOM 双风格 API 全解【免费下载链接】rapidjsonA fast JSON parser/generator for C with both SAX/DOM style API项目地址: https://gitcode.com/GitHub_Trending/ra/rapidjsonRapidJSON 是腾讯开源的 C JSON 解析器与生成器当前仓库版本 v1.1.0见 CMakeLists.txt 中LIB_VERSION_STRING的定义核心特点是 header-only、无 STL/BOOST 依赖并同时提供 SAX 事件流与 DOM 树两种操作模型。本文基于仓库中文主文档 readme.zh-cn.md 展开覆盖安装、构建、测试的完整流程配合仓库内的示例代码与头文件实现讲清解析 → 修改 → 生成这条主线在源码层面是如何落地的。项目定位与设计目标RapidJSON 的灵感来自 RapidXml是一个完全独立的 JSON 解析/生成库。README 将其设计目标归纳为五点这五点也决定了它在 C 生态中的典型使用场景小而全同时支持 SAX 和 DOM 风格 APISAX 解析器核心代码只有约 500 行。对应实现上SAX 侧是 reader.h 中的GenericReader模板化为ReaderDOM 侧是 document.h 中的GenericDocument模板化为Document。值得注意的是doc/features.zh-cn.md 明确指出DOM 风格 API 实际上是由 SAX 风格 API 实现的——GenericDocument内部实现了一组 SAX Handler 接口来接收解析事件SAX 更快DOM 更易用可按场景选择。快模板 内联函数降低函数调用开销内置优化的 Grisu2 浮点解析/生成实现internal/dtoa.h、internal/strtod.h并可选启用 SSE2/SSE4.2 指令加速。在 reader.h 中可以看到条件编译分支#if defined(RAPIDJSON_SSE42)时走_mm_crc32等向量化的字符串拷贝路径RAPIDJSON_SSE2时走__m128i路径否则回退到普通循环。独立不依赖 BOOST 甚至 STL头文件只包含cstdio、cstdlib、cstring、inttypes.h、new、stdint.h且不使用 C 异常和 RTTI。内存友好在大部分 32/64 位机器上每个 JSON 值只占 16 字节字符串除外。从源码结构看GenericValuedocument.h 起内部用一个union data_同时承载字符串/对象/数组/数字等载荷并以位域f.flags标记值类型v1.1 起在 x86-64 上将单个Value的开销从 24 字节压缩到了 16 字节。Unicode 友好支持 UTF-8、UTF-16、UTF-32大端/小端的编码检测、校验与转码支持代理对surrogate pair和\u0000空字符。编码层实现在 encodings.h例如可以读入一个 UTF-8 文件在解析进 DOM 时把其中的 JSON 字符串转码成 UTF-16 存储。在标准符合性方面README 声明 RapidJSON 应完全符合 RFC7159/ECMA-404并支持可选的放宽语法。doc/features.zh-cn.md 进一步列出了支持 JSON PointerRFC6901、JSON Schema Draft v4 等能力。v1.1 版本亮点当前仓库的版本号为 1.1.02016-08-25 发布见 CHANGELOG.md。v1.1 的主要新增能力JSON Pointerpointer.h实现GenericPointer可用类似/project/stars的路径表达更简洁地访问与修改 DOM配套文档见 doc/pointer.zh-cn.md。JSON Schemaschema.h在解析或生成 JSON 时进行 schema 校验配套文档见 doc/schema.zh-cn.md。放宽的 JSON 语法详见 doc/dom.zh-cn.md单行//与多行/* */注释、对象/数组尾随逗号、NaN/Infinity作为 double 值。这些功能默认全部关闭需要显式传入解析标志见下文解析标志小节。C11 范围 for 循环可直接for (auto member : obj.GetObject())遍历对象成员见 doc/tutorial.zh-cn.md。内存开销优化x86-64 架构下单个Value从 24 字节缩减至 16 字节。其他改动可参考完整的 CHANGELOG.md。平台兼容性README 列出曾测试过的平台/编译器组合Visual C 2008/2010/2013Windows32/64 位GNU C 3.8.xCygwinClang 3.4Mac OS X32/64 位及 iOSClang 3.4Android NDK这些是曾测试通过的组合不代表对更新的编译器/平台的承诺README 同时建议用户在自有平台自行构建并运行单元测试来验证。从 CMakeLists.txt 可以看到构建脚本目前实际为 GCC、Clang含 AppleClang、MSVC 和 XL 四类编译器做了专门的编译选项处理GCC/Clang 下默认开启-Wall -Wextra -Werror与-marchnative等因此在新平台上构建遇到问题时可以先从这些选项入手调整。安装与构建RapidJSON 是只有头文件的库最简单的集成方式就是把include/rapidjson目录复制到系统或项目的 include 路径中编译器只需加上对应的-I即可无需链接任何库文件。仓库自带的测试与示例构建依赖CMake≥ 3.5见 CMakeLists.txt 中CMAKE_MINIMUM_REQUIRED(VERSION 3.5)可选Doxygen用于生成文档可选googletest用于单元及性能测试位于thirdparty/gtest子模块中构建步骤执行git submodule update --init获取 thirdparty 子模块googletest。在仓库根目录下创建build目录。进入build目录执行cmake ..完成配置Windows 用户也可用 cmake-gui。Windows 下编译 build 目录中的 solutionLinux 下在 build 目录运行make。构建成功后编译出的测试与示例可执行文件位于bin目录CMakeLists.txt 中通过CMAKE_RUNTIME_OUTPUT_DIRECTORY统一指向${CMAKE_BINARY_DIR}/bin生成的文档位于 build 树的doc/html。运行测试可在 build 目录执行make test或ctestctest -V可输出详细日志。常用 CMake 配置项根 CMakeLists.txt 提供了以下开关可根据需要调整选项默认值作用RAPIDJSON_BUILD_DOCON构建文档依赖 DoxygenRAPIDJSON_BUILD_EXAMPLESON构建example/下的示例程序RAPIDJSON_BUILD_TESTSON构建单元测试与性能测试RAPIDJSON_BUILD_CXX11/CXX17/CXX20ON / OFF / OFF构建标准RAPIDJSON_BUILD_ASAN/RAPIDJSON_BUILD_UBSANOFF启用地址/未定义行为 sanitizerGCC ≥ 4.8/4.9RAPIDJSON_HAS_STDSTRINGOFF定义宏RAPIDJSON_HAS_STDSTRING启用std::string重载 APIRAPIDJSON_USE_MEMBERSMAPOFF定义宏RAPIDJSON_USE_MEMBERSMAP1用 map 存储对象成员若不需要文档可关闭以加快配置cmake -DRAPIDJSON_BUILD_DOCOFF ..。此外也可以把库安装到系统在具管理权限下从 build 目录执行make install。安装后其他 CMake 项目只需在CMakeLists.txt中加入find_package(RapidJSON)即可使用RapidJSONConfig.cmake.in 与 RapidJSONConfigVersion.cmake.in 会随之生成include/rapidjson头文件会按 CMakeLists.txt 中的install(DIRECTORY ...)规则装到 include 目录。用法一览解析—修改—生成三步走README 给出的最小完整示例来自 example/simpledom/simpledom.cpp它演示了把 JSON 字符串解析为 DOM → 修改 DOM → 把 DOM 序列化为 JSON 字符串的完整闭环// rapidjson/example/simpledom/simpledom.cpp #include rapidjson/document.h #include rapidjson/writer.h #include rapidjson/stringbuffer.h #include iostream using namespace rapidjson; int main() { // 1. 把 JSON 解析至 DOM。 const char* json {\project\:\rapidjson\,\stars\:10}; Document d; d.Parse(json); // 2. 利用 DOM 作出修改。 Value s d[stars]; s.SetInt(s.GetInt() 1); // 3. 把 DOM 转换stringify成 JSON。 StringBuffer buffer; WriterStringBuffer writer(buffer); d.Accept(writer); // Output {project:rapidjson,stars:11} std::cout buffer.GetString() std::endl; return 0; }注意该示例刻意没有处理潜在错误生产代码中必须检查Parse的返回值GenericDocument::Parse返回ParseResult可像布尔量一样判断d.HasParseError()获取错误码。结合源码可以把三步拆开看第 1 步d.Parse(json)Document的Parse重载定义在 document.h默认使用kParseDefaultFlags走流式解析路径同一文件里还有ParseInsitu原位解析把 DOM 的字符串直接指向原 JSON 缓冲区的内部位置省去字符串复制等重载。第 2 步d[stars]/SetIntValue提供GetInt/SetInt/GetDouble/IsInt等类型化访问器类型转换时内部会检查数值范围例如GetInt在值不是 32 位有号整数时断言失败。第 3 步d.Accept(writer)Value实现了 Visitor 接口Accept会把 DOM 以一组事件形式重放给 writer.h 中的Writer。这也正是 DOM 与 SAX 共享事件模型DefaultHandler反向消费的体现——同一个事件集合既可以由Reader产生也可以由 DOM 重放。PrettyWriter是其带缩进换行的变体StringBuffer则是承接输出的内存流。解析标志放宽语法的开关v1.1 引入的注释、尾随逗号、NaN/Infinity 支持均由 reader.h 中的位标志控制需要手动传给Parse的模板参数或经RAPIDJSON_PARSE_DEFAULT_FLAGS宏自定义默认值标志值说明kParseIterativeFlag4迭代式解析函数调用栈开销恒定适合解析嵌套极深的 JSON递归式解析器默认更快但极端情况下可能栈溢出kParseCommentsFlag32允许//单行与/* */多行注释kParseTrailingCommasFlag128允许对象/数组结束前的尾随逗号kParseNanAndInfFlag256允许把NaN、Inf、Infinity、-Inf、-Infinity解析为 double例如d.Parserapidjson::kParseCommentsFlag(json)即可接受含注释的输入。错误处理机制RapidJSON 不使用异常报告解析错误可选通过宏重定义实现而是通过ParseResult返回错误码与偏移量错误码定义在 error/error.h。从 reader.h 的文档注释可以看到用户甚至可以重定义RAPIDJSON_PARSE_ERROR_NORETURN宏把解析错误改成抛出自定义异常这是该库错误机制预留的定制点。示例导航从仓库 example 目录按 API 风格分类README 列出的示例对应example/目录按 API 风格可分为四类可作为不同场景的模板直接参考DOM APItutorial/tutorial.cppDOM API 基本用法覆盖创建、增删改查各类值。SAX APIsimplereader/simplereader.cpp使用Reader解析 JSON 时打印所有 SAX 事件。condense/condense.cpp移除 JSON 中所有空白符的命令行工具。pretty/pretty.cpp为 JSON 加入缩进与换行的命令行工具使用PrettyWriter。capitalize/capitalize.cpp把 JSON 中所有字符串改为大写的命令行工具。messagereader/messagereader.cpp用 SAX API 解析一个 JSON 报文。serialize/serialize.cpp用 SAX API 序列化 C 对象生成 JSON。jsonx/jsonx.cpp实现JsonxWriter把 SAX 事件写成 JSONx一种 XML 格式。Schema APIschemavalidator/schemavalidator.cpp用 JSON Schema 校验 JSON 的命令行工具。进阶prettyauto/prettyauto.cpppretty的修改版可自动处理任意 UTF 编码的 JSON 输入。parsebyparts/parsebyparts.cppAsyncDocumentParser类用 C11 线程逐段解析 JSON对应文件为 example/parsebyparts/parsebyparts.cpp。filterkey/filterkey.cpp移除指定键值的命令行工具。filterkeydom/filterkeydom.cpp同样的工具但演示如何用 SAX 生成器填充一个Document。除 README 列出的示例外仓库还包含 example/archiver/把 DOM 存为自定义二进制格式等进阶案例以及 example/README 之外的 CMakeLists 中注册的其余可执行目标均可直接构建运行。与 DOM 细节相关的补充README 的五点特性中内存友好值得再展开除了 16 字节的Value布局外解析过程默认使用 internal/stack.h 中的栈式分配器MemoryPoolAllocator定义于 allocators.h——它是顺序分配、不允许单独释放的非常适合解析期间集中分配、整体销毁的使用模式用户也可以提供预分配缓冲区达到全程不触发 CRT 分配地解析多个 JSON。此外 doc/features.zh-cn.md 提到Value内对短字符串做了内联优化UTF-8 下 64 位架构最多内联存储若干字符无需额外分配这也是 16 字节布局能容纳字符串指针 长度信息的原因之一。小结RapidJSON 是 header-only 库把include/rapidjson加入 include 路径即可使用CMake 项目可通过find_package(RapidJSON)集成。构建测试与示例git submodule update --init→cmake→make→make test/ctest -V产物在bin目录。最小闭环是Document::Parse→ 修改Value→Writer/PrettyWriterStringBuffer序列化完整可运行代码在 example/simpledom/simpledom.cpp。事件SAX模型是库的统一底层DOM 由 SAX 实现DOM 又能把事件重放给 Writer对性能和内存敏感的场景直接用Reader 自定义 Handler对易用性敏感的场景用Document。v1.1 的 JSON Pointer、JSON Schema 与放宽语法注释/尾逗号/NaN/Inf分别对应 pointer.h、schema.h 和reader.h中的解析标志位可按需开启。深入阅读建议从 doc/tutorial.zh-cn.md教程、doc/dom.zh-cn.mdDOM API、doc/sax.zh-cn.mdSAX API开始配合test/unittest下的各测试文件验证具体行为。【免费下载链接】rapidjsonA fast JSON parser/generator for C with both SAX/DOM style API项目地址: https://gitcode.com/GitHub_Trending/ra/rapidjson创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻