You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:55:19