nlohmann/json作为一款高效易用的C++ JSON库,其独特的Tagged Union架构和ADL序列化机制让开发者能够像操作STL容器一样处理JSON数据,同时支持多种二进制格式扩展。
能力适用场景不适用场景STL 格式访问与遍历配置文件读写、HTTP JSON 响应构建流式增量解析(需 SAX 手动实现)ADL 自动类型转换结构体与 JSON 双向映射超大规模 JSON(>100MB)零拷贝解析JSON Pointer (RFC 6901)深层嵌套路径定位频繁路径查询(无缓存机制)JSON Patch (RFC 6902)运行时动态修改 JSON 文档高并发修改(非线程安全)
架构与流程
核心模块
模块核心职责输入 → 输出Lexer将字节流切分为 Token 流原始字节 → token_type 枚举Parser递归下降语法分析,驱动 SAX 事件Token 流 → SAX 事件调用json_sax定义解析事件协议(纯虚接口)事件信号 → bool 继续/终止json_valueTagged Union 存储 JSON 值value_t 标签 + 联合体 → 具体值adl_serializerADL 实现类型转换basic_json ↔ 自定义类型serializerDOM 递归序列化为文本/二进制basic_json → 字节流
解析流程
原理与设计
关键抽象与机制
Tagged Union
通过value_t枚举和json_value联合体实现核心数据存储,basic_json仅包含两个成员:
value_t m_type = value_t::null; // 1 byte discriminator
json_value m_value = {}; // tagged union
json_value联合体中,复合类型使用指针存储,标量类型直接内联:
union json_value {
object_t* object; // heap-allocated
array_t* array; // heap-allocated
string_t* string; // heap-allocated
binary_t* binary; // heap-allocated
boolean_t boolean; // inline
number_integer_t number_integer; // inline
number_unsigned_t number_unsigned; // inline
number_float_t number_float; // inline
};
这种设计保证basic_json对象大小固定为16字节,与STL容器兼容。
SAX 双路径解析
解析器不直接构建DOM,而是通过json_sax接口发射事件,支持三种解析模式:
json_sax_dom_parser:构建完整DOM
json_sax_dom_callback_parser:支持回调过滤子树
json_sax_acceptor:仅校验语法
ADL 类型转换
当调用json.get<MyType>()时,类型转换查找链如下:
首先查找adl_serializer::from_json
其次在nlohmann命名空间查找
最后在用户类型所在命名空间查找
核心设计
Header-Only
单文件约25000行,每个包含的翻译单元都需完整编译。v3.11+提供json_fwd.hpp缓解编译开销。
指针存储
复合类型使用指针存储实现:
固定对象大小
高效移动语义
空值不分配内存
SAX 事件驱动
虽然引入虚函数调用开销,但带来:
回调过滤能力
格式无关解析管道
自定义SAX消费者的扩展性
源码地图
json.hpp (single-header amalgamation, ~25000 lines)
├── value_t