如何用nlohmann::json序列化/反序列化自定义类模板?
问题:nlohmann::json模板类序列化/反序列化失败
以下代码在执行json转换时出现错误:
template<typename T> class MyType { T data; }; template<typename T> void from_json(MyType<T>& t, const nlohmann::json& j) {} template<typename T> void to_json(const MyType<T>& t, nlohmann::json& j) {} int main() { MyType<std::string> f; nlohmann::json j = f; //error f = j.template get<MyType<std::string>>(); //error }
我正在编写基于nlohmann::json的库类,希望避免让用户为每个模板实例编写重复的序列化代码,请问有没有解决办法?如果没有,编译器报错的具体原因是什么?
报错原因
核心问题是序列化/反序列化函数的参数顺序完全写反了。nlohmann::json要求的标准函数签名为:
- 序列化(to_json):第一个参数是
nlohmann::json&,第二个是待序列化的自定义类型 - 反序列化(from_json):第一个参数是
const nlohmann::json&,第二个是待反序列化的自定义类型引用
你的代码把自定义类型放在了第一个参数位置,导致nlohmann::json的内部逻辑无法找到匹配的序列化函数,进而触发编译错误。
此外,nlohmann::json依赖ADL(参数依赖查找)机制定位序列化函数,若自定义类型在特定命名空间下,序列化函数也需放在同命名空间内,否则可能出现查找失败的情况。
解决办法
1. 修正函数参数顺序
调整to_json和from_json的参数顺序,匹配nlohmann::json的要求,同时补充具体的序列化逻辑:
#include <nlohmann/json.hpp> #include <string> using json = nlohmann::json; template<typename T> class MyType { public: // 需开放数据访问权限,或提供getter/setter用于序列化 T data; }; // 序列化:json在前,自定义类型在后 template<typename T> void to_json(json& j, const MyType<T>& t) { j["data"] = t.data; } // 反序列化:json在前,自定义类型引用在后 template<typename T> void from_json(const json& j, MyType<T>& t) { j.at("data").get_to(t.data); } int main() { MyType<std::string> f; json j = f; // 正常编译 f = j.get<MyType<std::string>>(); // 正常编译 }
2. 利用命名空间优化ADL查找(推荐)
如果你的库类位于自定义命名空间中,将序列化函数放在同一命名空间下,这样ADL会自动匹配,无需用户额外配置,完美避免重复代码:
#include <nlohmann/json.hpp> #include <string> using json = nlohmann::json; namespace mylib { template<typename T> class MyType { T data; public: const T& get_data() const { return data; } void set_data(const T& val) { data = val; } }; // 同命名空间下的序列化函数,ADL自动识别 template<typename T> void to_json(json& j, const MyType<T>& t) { j["data"] = t.get_data(); } template<typename T> void from_json(const json& j, MyType<T>& t) { T val; j.at("data").get_to(val); t.set_data(val); } } // namespace mylib int main() { mylib::MyType<std::string> f; json j = f; // 正常工作 f = j.get<mylib::MyType<std::string>>(); // 正常工作 }
内容的提问来源于stack exchange,提问作者TwistedBlizzard
相关产品推荐
相关产品推荐

