第四章:基于反射的 Json 反序列化 前一章我们已经用编译期反射实现了 Json 序列化,把一个聚合类型一次性吐成一段 Json 字符串,不需要手写拼接。 这章做反方向的事情: 给定一段 Json 文本,把它自动填充进一个结构体对象里,支持嵌套结构体、顺序容器、关联容器等常见组合。 最终对外只保留一个接口: 1 2 3 4 5 6 7 8 tinyrefl::Complex obj{}; const char* json = R"({ "id": 42, "name": "tinyrefl", "values": [1, 2, 3] })"; auto st = tinyrefl::reflection_from_json(obj, json); 这里我采用不构建 DOM,直接基于RapidJSON的流式 SAX 接口,把事件派发到对应的结构体成员。 主要思路: 由于RapidJson的SAX接口只提供回调,所以对于递归反序列化,还需要我们自己维护一个解析栈来处理嵌套情况 同时,RapidJson对于数组类型和普通类型的回调方式不同,所以这里需要分别进行处理 剩下的就是使用RapidJson的接口了,RapidJson相关文档:https://rapidjson.org/zh-cn/ 结构体成员KV化 到反序列化这里,前面的铺垫已经很充分了: members_count_v<T> 能在编译期算出成员个数 struct_members_to_array<T>() 能拿到成员名数组 struct_members_to_tuple<T>() 能拿到成员引用 tuple(在有对象实例的前提下) 序列化的时候,我们只需要在“有对象”的场景下遍历一遍成员,把 (member_name, member_reference)这一对在运行时交给 to_json_value 就行,所以直接用 tuple + 泛型 lambda 遍历就够了。 反序列化就不一样了,真正要解决的是下面这个问题: 当 RapidJSON 回调告诉我「现在读到了 key = ‘id’」,如何在 O(1) 时间里找到这个成员在结构体里的“位置”和“类型”,然后把后续的值事件填到正确的成员上? 也就是说,我们需要把“结构体的成员元信息”预先组织成某种 Key → Value 的形式: ...







