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

nlohmann JSON中模板类from_json/to_json序列化反序列化报错排查

解决nlohmann JSON模板类序列化/反序列化的编译错误

问题根源分析

你的代码存在三个核心问题,导致编译失败:

  1. 缺少Test类的序列化逻辑:仅为Test的adl_serializer特化了from_json反序列化函数,但未提供对应的to_json序列化函数,编译器无法将Test对象转换为JSON对象。
  2. Data类未实现to_json函数:尝试序列化Data时,编译器自动生成的默认逻辑无法处理Test成员,触发类型匹配错误。
  3. SetCurrentOutput存在空值风险:直接调用std::optional::value()会在可选值为空时触发未定义行为,且原方法的参数类型与成员变量不匹配。

解决方案及修正代码

以下是完整的修正代码,包含所有问题的修复:

#include <vector>
#include <optional>
#include <iostream>
#include <memory>
#include <Eigen/Dense>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

template <class InputType = float, class OutputType = bool>
class Test {
public:
    struct InputOutputPair {
        InputType input;
        OutputType output;
    };

    void SetLeftThreshold(InputType threshold) {
        m_leftThreshold = threshold;
    }

    void SetRightThreshold(InputType threshold) {
        m_rightThreshold = threshold;
    }

    // 修正参数类型:与成员变量OutputType匹配
    void SetLeftOutput(OutputType output) {
        m_leftOutput = output;
    }

    // 修正参数类型:与成员变量OutputType匹配
    void SetRightOutput(OutputType output) {
        m_rightOutput = output;
    }

    void SetThresholdsMidpoint(InputType midThreshold) {
        m_thresholdsMidpoint = midThreshold;
    }

    // 修复空值处理逻辑:避免直接调用value()导致崩溃
    void SetCurrentOutput(std::optional<OutputType> currentOutput) {
        m_currentOutput = currentOutput;
    }

    // 添加getter方法,用于序列化时访问私有成员
    InputType GetLeftThreshold() const { return m_leftThreshold; }
    InputType GetRightThreshold() const { return m_rightThreshold; }
    OutputType GetLeftOutput() const { return m_leftOutput; }
    OutputType GetRightOutput() const { return m_rightOutput; }
    InputType GetThresholdsMidpoint() const { return m_thresholdsMidpoint; }
    const std::optional<OutputType>& GetCurrentOutput() const { return m_currentOutput; }

private:
    // 初始化成员变量,避免未定义值
    InputType m_leftThreshold{};
    InputType m_rightThreshold{};
    OutputType m_leftOutput{};
    OutputType m_rightOutput{};
    InputType m_thresholdsMidpoint{};
    std::optional<OutputType> m_currentOutput{};
};

class Data {
public:
    Test<> m_leftSwitch;
};

// 实现Data的反序列化
inline void from_json(const json& j, Data& hsd) {
    j.at("isLeftSwitch").get_to(hsd.m_leftSwitch);
}

// 实现Data的序列化
inline void to_json(json& j, const Data& hsd) {
    j = {{"isLeftSwitch", hsd.m_leftSwitch}};
}

namespace nlohmann {
template <class InputType, class OutputType>
struct adl_serializer<Test<InputType, OutputType>> {
    // 反序列化逻辑:显式指定类型转换,避免隐式转换歧义
    inline static void from_json(const json& j, Test<InputType, OutputType>& hsd) {
        hsd.SetLeftThreshold(j.at("leftThreshold").get<InputType>());
        hsd.SetRightThreshold(j.at("rightThreshold").get<InputType>());
        hsd.SetLeftOutput(j.at("leftOutput").get<OutputType>());
        hsd.SetRightOutput(j.at("rightOutput").get<OutputType>());
        hsd.SetThresholdsMidpoint(j.at("thresholdMidPoint").get<InputType>());
        
        // 处理可选值:兼容JSON中键不存在或为null的情况
        hsd.SetCurrentOutput(j.value("currentOutput", std::nullopt));
    }

    // 补全序列化逻辑:映射Test成员到JSON键值对
    inline static void to_json(json& j, const Test<InputType, OutputType>& hsd) {
        j = {
            {"leftThreshold", hsd.GetLeftThreshold()},
            {"rightThreshold", hsd.GetRightThreshold()},
            {"leftOutput", hsd.GetLeftOutput()},
            {"rightOutput", hsd.GetRightOutput()},
            {"thresholdMidPoint", hsd.GetThresholdsMidpoint()},
            {"currentOutput", hsd.GetCurrentOutput()}
        };
    }
};
} // namespace nlohmann

int main() {
    // 测试序列化
    Data data;
    data.m_leftSwitch.SetLeftThreshold(1.0f);
    data.m_leftSwitch.SetRightThreshold(2.0f);
    data.m_leftSwitch.SetLeftOutput(true);
    data.m_leftSwitch.SetRightOutput(false);
    data.m_leftSwitch.SetThresholdsMidpoint(1.5f);
    data.m_leftSwitch.SetCurrentOutput(true);

    json j = data;
    std::cout << "Serialized JSON:\n" << j.dump(4) << std::endl;

    // 测试反序列化
    Data new_data;
    from_json(j, new_data);
    std::cout << "\nDeserialized left threshold: " << new_data.m_leftSwitch.GetLeftThreshold() << std::endl;
}

关键修正点说明

  1. 补全Test的序列化逻辑:在adl_serializer中添加to_json函数,通过getter方法访问私有成员,完成JSON映射。
  2. 修复参数类型不匹配:将SetLeftOutput/SetRightOutput的参数类型从InputType改为OutputType,与成员变量类型一致。
  3. 完善可选值处理:使用json::value()方法兼容currentOutput键不存在或为null的场景,避免空optional的非法访问。
  4. 初始化成员变量:为Test的私有成员添加默认初始化,避免序列化时出现不确定值。

内容的提问来源于stack exchange,提问作者Nitron_707

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 21:13:11