C++轻量级流式JSON解析器采用SAX事件驱动设计,O(1)内存占用,支持UTF-8、转义处理与零拷贝string_view回调。
用 C++ 实现一个轻量级流式 JSON 解析器,核心是采用 SAX(Simple API for XML)风格——即事件驱动、不构建完整 DOM 树,边读边处理,内存占用恒定(O(1)),特别适合大文件、嵌入式或实时数据流场景。
不依赖第三方库(如 jsoncpp、nlohmann/json),手动解析 UTF-8 字节流,识别结构变化(对象开始/结束、数组开始/结束、键名、字符串/数字/布尔值/空值),每识别出一个语义单元,立即触发用户注册的回调函数。
关键状态机要素:
{/} 和 [/])' '、'\t'、'\n'、'\r'),不回溯std::from_chars(C++17)或简易状态机避免 std::stod 开销定义简洁的事件枚举和回调签名,保持低耦合:
enum class JsonEventType {
START_OBJECT, END_OBJECT,
START_ARRAY, END_ARRAY,
KEY, STRING,
NUMBER, BOOL,
NULL_VALUE
};
using JsonHandler = std::function;
注意:KEY 仅在对象内、冒号前触发;STRING 对应字符串字面量(已去引号、已解转义);NUMBER 的 payload 是原始数字文本(如 "123" 或 "-3.14e+2"),由用户决定是否转换。
JSON 字符串必须支持 Unicode,且需正确处理 \uXXXX 转义。简易做法:
\" → 输出 "
\\ → 输出 \
\u 后跟 4 个十六进制字符 → 转为 UTF-8 编码字节序列(需处理代理对,但简单场景可先忽略 BMP 外字符)推荐用查表法快速判断 hex 字符,避免 std::stoi 开销。
+ 用户缓冲区管理不内部缓存整个 token,而是将 std::string_view 指向输入缓冲区的子段(前提是输入生命周期可控)。例如:
"name": "Alice" 时,对 "name" 触发 KEY 事件,传入 string_view{buf + pos, 4}
"Alice" 触发 STRING,传入 string_view{buf + pos2, 5}
整个解析器自身只需几十字节栈空间(状态、深度、临时索引),不 new/malloc。
基本上就这些。写起来约 300–500 行 C++17 代码,能覆盖 RFC 8259 核心子集,兼顾性能与可读性。真要上生产,建议在关键路径加断言和错误位置追踪(行号/列号),但不影响流式本质。