该项目是基于Qt5,利用C++11实现的半自动生成解析Json工具。
当写项目时,可能需要写大量的Json,比如有1000个结构体,需要完成其Json的生成及解析,而每写一个数据就需要实现对应的类型转换,极其繁琐,稍不注意,可能写错。如key存错,生成和解析的key不一致,可能需要花费好大的精力去排除bug。还有类型转换不一致,这个一般情况下编译器会帮查找,但是前后规则不同编译器是检查不出的,如下错误代码:
QJsonObject obj;
QDateTime time, timeNew;
//生成
obj.insert("time", time.toMSecsSinceEpoch());
//解析
timeNew = QDateTime::fromString(obj.value("time").toString());
难道每写一个数据,都需要程序员去检查吗?惊呼 “打工人好难呀!!!”
所以利用模板小试牛刀一下子,实现一个半自动Json工具。
直接上源码:
#include <QJsonObject>
#include <QJsonArray>
#include <QStringList>
#include <QString>
#include <QDateTime>
#include <iostream>
#include <type_traits>
#define GJSONTOOL_TOJSON(obj, Data) \
JsonTool::CreatJson(obj, Data, JsonTool::dowithName(#Data));
#define GJSONTOOL_TOVALUE(obj, Data) \
JsonTool::CreatValue(obj, Data, JsonTool::dowithName(#Data));
namespace JsonTool {
inline void toValue(QJsonObject& obj, QString& T_Data, const QString& strKey)
{
T_Data = obj.value(strKey).toString();
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type , std::string>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = obj.value(strKey).toString().toStdString();
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type , QString>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = obj.value(strKey).toString();
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type, int>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = obj.value(strKey).toInt();
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type, short>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = (short)obj.value(strKey).toInt();
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type, uint>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = (uint)obj.value(strKey).toInt();
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type, ushort>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = (ushort)obj.value(strKey).toInt();
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type, QDateTime>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
QString format = "yyyy-MM-ddThh:mm:ss";
T_Data = QDateTime::fromString(obj.value(strKey).toString(), format);
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type, QStringList>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
for(const auto& chil : obj.value(strKey).toArray())
{
T_Data.append(chil.toString());
}
}
template <typename T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = (typename std::decay<T>::type)obj.value(strKey).toDouble(); //浮点型
}
template <typename T, typename std::enable_if<std::is_enum<typename std::decay<T>::type>::value, int>::type = 0>
inline void toValue(QJsonObject& obj, T& T_Data, const QString& strKey)
{
T_Data = (typename std::decay<T>::type)obj.value(strKey).toInt();
}
template <typename T, typename = void>
struct toJson
{
void operator()(QJsonObject& obj, T&& T_Data, const QString& strKey)
{
obj.insert(strKey, T_Data);
}
};
template <typename T>
struct toJson<T, typename std::enable_if<std::is_same<typename std::decay<T>::type, QStringList>::value>::type>
{
void operator()(QJsonObject& obj, T&& listData, const QString& strKey)
{
QJsonArray arr;
for(const auto& child : listData)
arr.append(child);
obj.insert(strKey, arr);
}
};
template <typename T>
struct toJson<T, typename std::enable_if<std::is_same<typename std::decay<T>::type, QDateTime>::value>::type>
{
void operator()(QJsonObject& obj, T&& TData, const QString& strKey)
{
QString format = "yyyy-MM-ddThh:mm:ss";
obj.insert(strKey, TData.toString(format));
}
};
template <typename T>
struct toJson<T, typename std::enable_if<std::is_same<typename std::decay<T>::type, std::string>::value>::type>
{
void operator()(QJsonObject& obj, T&& TData, const QString& strKey)
{
obj.insert(strKey, QString::fromStdString(TData));
}
};
inline QString dowithName(const QString& strName)
{
if(strName.contains("."))
{
return strName.split(".").last();
}
else
return strName;
}
template <typename T>
inline void CreatJson(QJsonObject& obj, T&& TData, const QString& strKey)
{
toJson<T>()(obj, TData, strKey);
}
template <typename T>
inline void CreatValue(QJsonObject& obj, T& TData, const QString& strKey)
{
toValue<T>(obj, TData, strKey);
}
}
这里用到了模板的穷举,把一些常用的类型穷举实现出来,如果大家有其他的类型,可以在此基础上进行添加。如果大家有看不懂的地方,那就去百度或者问人工智能,这里我就不一一解释了。有其他问题可以留言。
下面是进行调用:
//先定义一个结构体
//学生信息
struct stuStudent
{
enum ENGender
{
ENG_Boy = 1,
ENG_Girl
};
QString strName;
std::string strNickName;
ENGender eGen;
int iAge;
double dHeight;
QStringList listLoveGirls;
QDateTime tCurrTime;
};
//生成Json
QJsonObject builtToJson(stuStudent &stuData)
{
QJsonObject obj;
GJSONTOOL_TOJSON(obj, stuData.iAge);
GJSONTOOL_TOJSON(obj, stuData.dHeight);
GJSONTOOL_TOJSON(obj, stuData.strName);
GJSONTOOL_TOJSON(obj, stuData.eGen);
GJSONTOOL_TOJSON(obj, stuData.listLoveGirls);
GJSONTOOL_TOJSON(obj, stuData.tCurrTime);
GJSONTOOL_TOJSON(obj, stuData.strNickName);
return obj;
}
//解析Json
void fromJsonToData(QJsonObject &obj, stuStudent &stuData)
{
GJSONTOOL_TOVALUE(obj, stuData.iAge);
GJSONTOOL_TOVALUE(obj, stuData.dHeight);
GJSONTOOL_TOVALUE(obj, stuData.strName);
GJSONTOOL_TOVALUE(obj, stuData.eGen);
GJSONTOOL_TOVALUE(obj, stuData.listLoveGirls);
GJSONTOOL_TOVALUE(obj, stuData.tCurrTime);
GJSONTOOL_TOVALUE(obj, stuData.strNickName);
}
上边的调用很简单,生成只需要调用GJSONTOOL_TOJSON, 解析只需要调用GJSONTOOL_TOVALUE,不需要程序员去实现toInt,toString等等的类型转换,也不需要人为去传入key。省去大量的时间,以及调试时间。惊呼“哇哇哇!!!”
最终的调用:
int main(int argc, char *argv[])
{
stuStudent stuData;
stuData.strName = "王二麻子";
stuData.strNickName = "老王";
stuData.eGen = stuStudent::ENG_Boy;
stuData.iAge = 18;
stuData.dHeight = 178.88;
stuData.listLoveGirls << "翠花" << "小花" << "小甜甜" << "苍老师" ;
stuData.tCurrTime = QDateTime::currentDateTime();
//生成Json
QJsonObject obj = builtToJson(stuData);
//解析Json
stuStudent stuDataNew;
fromJsonToData(obj, stuDataNew);
int aaa = 1; //方便打断点
}
最终程序运行的结果 stuData 和 stuDataNew数据内容一模一样。大功告成!!!
读到这里就可以啦,快去好好工作吧。
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
下面是一些幼稚的文字,人文的东西可以让人放松一下。大概是本人2022年写的,谈不上诗,也分享一下,俗称开源。
无题
清水一笑芙蓉颜,
滟波浮去碧霞间。
恍然刹那一梦兮,
也罢,
逍遥归去皆随缘。
分享完毕,感谢大家的阅读哈,感谢特别感谢。