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

使用nlohmann::json宏将JSON转C++类遇错,求解决方案

修复nlohmann::json无法映射g::Game类的问题

错误信息

error: no matching function for call to ‘nlohmann::basic_json<>::get<g::Game>()’ 19 | game = data.get<g::Game>();

问题代码

Game类定义

namespace g{
class Game {
public:
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(Game, _name, audience)
private:
    uintptr_t _id; // unique id can act as an invitation code
    uintptr_t _ownerID;
    bool _started;
    std::vector<Connection> _players;
    std::string _name;
    //Bounds of player given in json file
    struct PlayerCount {
        int min;
        int max;
        NLOHMANN_DEFINE_TYPE_INTRUSIVE(PlayerCount, min, max)
    } player_count;
    bool audience;
    // map of { name_string -> { configurable_value , prompt_text } }
    std::map<std::string, std::pair<std::any, std::string>> setup;
    std::map<std::string, List> constants;
    std::map<std::string, List> variables;
    std::map<std::string, List> per_player;
    std::map<std::string, List> per_audience;
    std::vector<Rule> rules;
};
}

出错的反序列化代码

using json = nlohmann::json;
using namespace g;

InterpretJson::InterpretJson(string path){
    this->path = path;
    ifstream f(path);
    json jData = json::parse(f);
    f.close();
    data = jData;
}

void InterpretJson::interpret(Game& game){
   game = data.get<g::Game>(); //data是InterpretJson.h中定义的私有成员,类型为json
}

问题根源

  • 自定义类型未配置序列化:Connection、List、Rule这些自定义类型没有添加nlohmann的序列化宏,json无法识别并处理它们。
  • std::any无默认支持:nlohmann::json没有内置std::any的序列化逻辑,无法直接转换该类型。
  • 序列化宏成员不全:NLOHMANN_DEFINE_TYPE_INTRUSIVE仅声明了_name和audience,但Game类中还有其他需要从json加载的成员(如player_count、setup),未被纳入宏的成员无法完成映射。

修复步骤

1. 为自定义类型添加序列化宏

为Connection、List、Rule分别添加侵入式或非侵入式序列化宏,以List为例:

// 侵入式示例:在List类内部添加宏
struct List {
    std::vector<std::string> elements;
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(List, elements)
};

// 非侵入式示例:如果无法修改List类,在外部添加
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(List, elements)

2. 手动实现std::any的序列化逻辑

nlohmann::json不支持std::any,需根据业务场景编写转换函数(以支持int和string为例):

namespace nlohmann {
    template<>
    struct adl_serializer<std::any> {
        static void to_json(json& j, const std::any& val) {
            if (val.type() == typeid(int)) {
                j = std::any_cast<int>(val);
            } else if (val.type() == typeid(std::string)) {
                j = std::any_cast<std::string>(val);
            }
            // 按需添加其他需要支持的类型
        }

        static void from_json(const json& j, std::any& val) {
            if (j.is_number_integer()) {
                val = j.get<int>();
            } else if (j.is_string()) {
                val = j.get<std::string>();
            }
            // 对应添加反序列化逻辑
        }
    };
}

3. 更新Game类的序列化宏成员列表

将所有需要从json加载的成员加入NLOHMANN_DEFINE_TYPE_INTRUSIVE宏中,根据你的json结构调整:

namespace g{
class Game {
public:
    // 加入需要反序列化的成员,无需加载的成员可省略
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(Game, _name, audience, player_count, setup, constants, variables, per_player, per_audience, rules)
private:
    // ... 原有成员 ...
};
}

4. 优化反序列化调用(可选)

不需要创建临时Game对象再赋值,直接使用get_to方法写入已有对象:

void InterpretJson::interpret(Game& game){
   data.get_to(game); // 避免临时对象拷贝,提升效率
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:30:56