使用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
相关产品推荐
相关产品推荐

