to_json/from_json函数需与结构体同命名空间,嵌套类型须提前定义序列化函数,NLOHMANN_DEFINE_TYPE_INTRUSIVE宏限64字段且不支持定制逻辑。

直接用 to_json 和 from_json 函数就能做,不需要改类定义、不依赖反射、也不用写样板解析逻辑——前提是这两个函数在正确命名空间里,且参数签名匹配。
to_json / from_json 必须和结构体在同一个命名空间
这是最容易卡住的地方:如果 Person 在 user 命名空间里,那 to_json 也得写在 user 里,否则 nlohmann::json j = person; 会编译失败,报错类似 no matching function for call to 'to_json'。
- 不能放在全局命名空间(除非结构体本身也在全局)
- 不能放在
nlohmann命名空间(违反 ADL 规则,且可能引发 ODR 冲突) - 嵌套结构体要按顺序先定义内层的序列化函数,比如
Address的to_json得在Person的之前声明
NLOHMANN_DEFINE_TYPE_INTRUSIVE 宏适合快速原型,但有硬限制
一行宏能省掉手写函数,但它必须写在结构体定义内部,且只支持最多 64 个字段。超过就得切回手写 to_json。
- 用法示例:
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Person, name, age, email) - 字段名必须和成员变量名完全一致,不支持别名或条件跳过
- 无法处理敏感字段加密、默认值填充、字段重命名等定制逻辑
- 如果结构体是
final或含私有继承,宏会展开失败
嵌套结构体序列化时,子类型必须已可序列化
nlohmann::json 不会自动递归推导嵌套类型。比如 Person 里有个 Address 成员,那 Address 自身也得有对应的 to_json 函数,否则编译报错 no known conversion from 'Address' to 'json'。
- 顺序很重要:先定义
GeoPoint→ 再定义Address(含GeoPoint成员)→ 最后定义Person - 数组、
std::vector、std::map等 STL 容器默认支持,不用额外定义 - 指针类型(如
TreeNode*)必须显式判空,否则反序列化时解引用空指针会崩溃
真正麻烦的不是怎么写序列化函数,而是命名空间错位、嵌套依赖没理清、或者误以为宏能覆盖所有场景——这些地方一错,编译器不会告诉你“少写了哪个函数”,只会抛一堆模板展开失败的错误信息。


















