使用nlohmann JSON解析还原类实例的报错问题咨询
C++使用nlohmann/json解析JSON还原类实例的编译错误解决
我需要将One、Two两个类的实例按指定格式存入JSON,再解析JSON还原为类实例。目前已成功生成JSON,但解析还原时出现编译错误(错误代码含C3867、C2672等)。
错误信息
1>c:\users\212506\documents\visual studio 2015\projects\consoleapplication6\consoleapplication6\consoleapplication6.cpp(72): error C3867: 'One::Value1': non-standard syntax; use '&' to create a pointer to member
...
生成的JSON片段
{ "One",{ { "Value1", one.Value1() }, } }, { "Two",{ { "Value1", two.Value1() }, { "Value2", two.Value2() } } },
完整代码
#include "stdafx.h" #include <iostream> #include <string> #include <array> #include <initializer_list> #include "nlohmann/json.hpp" using nlohmann::json; class Two { public: Two() :m_Value1(0), m_Value2(0) {} Two(int val1, int val2) : m_Value1(val1), m_Value2(val2) { } int& Value1() { return m_Value1; } int& Value2() { return m_Value2; } public: int m_Value1; int m_Value2; }; class One { public: One() : m_Value1_1(0) {} One(int val1) : m_Value1_1(val1) { } int& Value1() { return m_Value1_1; } public: int m_Value1_1; }; std::string ToJsonString(One &one, Two &two) { nlohmann::json j = { { "One",{ { "Value1", one.Value1() }, } }, { "Two",{ { "Value1", two.Value1() }, { "Value2", two.Value2() } } }, }; std::cout << j.dump(4) << std::endl; std::string str = j.dump(4); return str; } void from_json(const json& j, One& one) { j.at("Value1").get_to(one.Value1()); } void from_json(const json& j, Two& two) { j.at("Value1").get_to(two.Value1()); j.at("Value2").get_to(two.Value2()); } void ToObjectsOne(std::string json, One &one1, Two &two1) { nlohmann::json data; try { data = nlohmann::json::parse(json); } catch (nlohmann::json::exception& exception) { std::cerr << "Exception[" << exception.what() << "]"; } one1 = data["One"].get<One>(); two1 = data["Two"].get<Two>(); } int main() { One one(10); Two two(10, 20); std::string jsonStr = ToJsonString(one, two); One one1; Two two1; ToObjectsOne(jsonStr, one1, two1); std::cout << one1.m_Value1_1<<std::endl; std::cout << two1.m_Value1 << std::endl; std::cout << two1.m_Value2 << std::endl; return 0; }
核心问题
请问是否可以使用One one = data["One"].get<One>();的方式获取数据?若不行,该如何从JSON中还原这两个类的实例?
问题分析与解决
首先,data["One"].get<One>()这种方式完全可以使用,编译错误的根源在于from_json函数的写法问题:
1. 编译错误原因
错误C3867是因为Visual Studio 2015对模板推导的支持存在缺陷,无法正确识别one.Value1()返回的int&作为get_to的参数;本质上是编译器误将成员函数调用识别为取成员函数指针的语法。
2. 两种修正方案
方案一:直接操作public成员变量(最简洁)
既然类的成员变量是public的,直接在from_json中赋值可以彻底避开函数调用的模板推导问题:
void from_json(const json& j, One& one) { one.m_Value1_1 = j.at("Value1").get<int>(); } void from_json(const json& j, Two& two) { two.m_Value1 = j.at("Value1").get<int>(); two.m_Value2 = j.at("Value2").get<int>(); }
方案二:显式指定get_to的模板参数
如果必须保留成员函数的调用,可以通过显式指定模板参数,帮助编译器正确推导类型:
void from_json(const json& j, One& one) { j.at("Value1").get_to<int>(one.Value1()); } void from_json(const json& j, Two& two) { j.at("Value1").get_to<int>(two.Value1()); j.at("Value2").get_to<int>(two.Value2()); }
3. 额外优化建议
- 将
ToObjectsOne的参数std::string json改为const std::string& json,避免不必要的字符串拷贝; - 确保使用的nlohmann/json版本兼容Visual Studio 2015(推荐v3.9.1及更早版本)。
修正后的完整代码(方案一)
#include "stdafx.h" #include <iostream> #include <string> #include <array> #include <initializer_list> #include "nlohmann/json.hpp" using nlohmann::json; class Two { public: Two() :m_Value1(0), m_Value2(0) {} Two(int val1, int val2) : m_Value1(val1), m_Value2(val2) { } int& Value1() { return m_Value1; } int& Value2() { return m_Value2; } public: int m_Value1; int m_Value2; }; class One { public: One() : m_Value1_1(0) {} One(int val1) : m_Value1_1(val1) { } int& Value1() { return m_Value1_1; } public: int m_Value1_1; }; std::string ToJsonString(One &one, Two &two) { nlohmann::json j = { { "One",{ { "Value1", one.Value1() }, } }, { "Two",{ { "Value1", two.Value1() }, { "Value2", two.Value2() } } }, }; std::cout << j.dump(4) << std::endl; return j.dump(4); } void from_json(const json& j, One& one) { one.m_Value1_1 = j.at("Value1").get<int>(); } void from_json(const json& j, Two& two) { two.m_Value1 = j.at("Value1").get<int>(); two.m_Value2 = j.at("Value2").get<int>(); } void ToObjectsOne(const std::string& jsonStr, One &one1, Two &two1) { nlohmann::json data; try { data = nlohmann::json::parse(jsonStr); } catch (const nlohmann::json::exception& exception) { std::cerr << "Exception[" << exception.what() << "]" << std::endl; } one1 = data["One"].get<One>(); two1 = data["Two"].get<Two>(); } int main() { One one(10); Two two(10, 20); std::string jsonStr = ToJsonString(one, two); One one1; Two two1; ToObjectsOne(jsonStr, one1, two1); std::cout << one1.m_Value1_1 << std::endl; std::cout << two1.m_Value1 << std::endl; std::cout << two1.m_Value2 << std::endl; return 0; }
内容的提问来源于stack exchange,提问作者user2094814
相关产品推荐
相关产品推荐

