这篇文章给大家分享的是有关C++中类结构体与json如何相互转换的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
之前写C#的时候,解析json
字符串一般使用的是开源的类库Newtonsoft.Json
,方法十分简洁,比如:
class Project
{
public string Input { get; set; }
public string Output { get; set; }
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
Project test = serializer.Deserialize<Project>(@"{"Input":"1","Output":"2"}");
一行代码就能将json字符串转为相应的类对象。
最近写C++需要处理一下json
数据,于是上github
找了很多很强大的开源库,像jsoncpp
、rapidjson
、json
,基本上都满足了开发需求,但想要做成像写C#那样子就要做二次开发。于是有了自己写一个简单的json转类 | 结构体的工具的想法(开源地址)。
需求如下:
只有头文件,方便使用
最多三行代码解决转换
支持类|结构体 与 json
的相互转换
支持多种基本数据类型,如int
、float
、string
、bool
等
支持STL基本类型,如vector
、list
、map<string
,T>等
支持嵌套关系
支持成员重命名,比方说json
中的关键字是name
,成员命名可写成Name或其他。
class Student
{
public:
string Name;
int Age;
AIGC_JSON_HELPER(Name, Age)//成员注册
AIGC_JSON_HELPER_RENAME("name","age")//成员重命名,不需要可以删除这条
};
int main()
{
//json转类对象
Student person;
JsonHelper::JsonToObject(person, R"({"name":"XiaoMing", "age":15})");
//类对象转json
string jsonStr;
JsonHelper::ObjectToJson(person, jsonStr);
return 0;
}
因为刚好rapidjson
只需要头文件就可以使用,所以选择了rapidjson
作为基础库,进行二次开发。
作为最底层的接口,只需要进行一个赋值的操作即可,后续如果想要增加一些其他类型支持,添加起来也比较方便。
static bool JsonToObject(int &obj, rapidjson::Value &jsonValue)
{
if (jsonValue.IsNull() || !jsonValue.IsInt())
return false;
obj = jsonValue.GetInt();
return true;
}
static bool JsonToObject(unsigned int &obj, rapidjson::Value &jsonValue)
{
if (jsonValue.IsNull() || !jsonValue.IsUint())
return false;
obj = jsonValue.GetUint();
return true;
}
static bool JsonToObject(int64_t &obj, rapidjson::Value &jsonValue)
{
if (jsonValue.IsNull() || !jsonValue.IsInt64())
return false;
obj = jsonValue.GetInt64();
return true;
}
//其他类型... ...
这里使用宏定义方式 + 可变参数模板的方式来实现,即可依次对注册的成员进行赋值
template <typename TYPE, typename... TYPES>
static bool WriteMembers(std::vector<std::string> &names, int index, rapidjson::Value &jsonValue, TYPE &arg, TYPES &... args)
{
if (!WriteMembers(names, index, jsonValue, arg))
return false;
return WriteMembers(names, ++index, jsonValue, args...);
}
template <typename TYPE>
static bool WriteMembers(std::vector<std::string> &names, int index, rapidjson::Value &jsonValue, TYPE &arg)
{
const char *key = names[index].c_str();
if (!jsonValue.HasMember(key))
return true;
if (!JsonToObject(arg, jsonValue[key]))
return false;
return true;
}
#define AIGC_JSON_HELPER(...) \
bool AIGC_CONVER_JSON_TO_OBJECT(rapidjson::Value &jsonValue, std::vector<std::string> &names) \
{ \
if (names.size() <= 0) \
names = aigc::JsonHelper::GetMembersNames(#__VA_ARGS__); \
return aigc::JsonHelper::WriteMembers(names, 0, jsonValue, __VA_ARGS__); \
}
自定义类由于并不清楚外界使用时,是否有按规定添加好成员注册接口,所以这里采用enable_if
的方式来尝试调用,编译的时候也就不会报错。
template <bool, class TYPE = void>
struct enable_if
{
};
template <class TYPE>
struct enable_if<true, TYPE>
{
typedef TYPE type;
};
template <typename T>
struct HasConverFunction
{
template <typename TT> static char func(decltype(&TT::AIGC_CONVER_JSON_TO_OBJECT));
template <typename TT> static int func(...);
const static bool has = (sizeof(func<T>(NULL)) == sizeof(char));
};
template <typename T, typename enable_if<HasConverFunction<T>::has, int>::type = 0>
static inline bool JsonToObject(T &obj, rapidjson::Value &jsonValue)
{
std::vector<std::string> names = LoadRenameArray(obj);
return obj.AIGC_CONVER_JSON_TO_OBJECT(jsonValue, names);
}
template <typename T, typename enable_if<!HasConverFunction<T>::has, int>::type = 0>
static inline bool JsonToObject(T &obj, rapidjson::Value &jsonValue)
{
return false;
}
/**
* @brief conver json string to class | struct
* @param obj : class or struct
* @param jsonStr : json string
*/
template <typename T>
static inline bool JsonToObject(T &obj, const std::string &jsonStr)
{
rapidjson::Document root;
root.Parse(jsonStr.c_str());
if (root.IsNull())
return false;
return JsonToObject(obj, root);
}
最核心的部分也就上面的几个模块,其他的都是一些琐碎的增加类型支持等操作。
感谢各位的阅读!关于“C++中类结构体与json如何相互转换”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。