之前貌似没有看过类似的代码

我们现在的要求就是直接在不知道类成员的情况下,把一个类丢进去就能生成一个Json字符串,也可以把一个字符串和一个类成员丢进去就能根据成员变量名匹配到元素并赋值,大概就这样

中心思想就是Q_PROPERTY宏提供了一个property类型,可以直接通过变量名称获得一个变量名称对应的字符串,比如int a;可以直接获得一个"a"的字符串,而且还可以知道这个a 的类型。并据此来进行字符串的封装和解析。

主要是为了开发方便,就可以直接把一个QObject对象扔进去返回一个字符串,也可以把一个Json字符串和指定类的对象扔进去就直接自动把类中对应的属性修改了,总的来说应该是用点用。

--2023.2.2稍微修改了一下,与原先的使用上会有点区别

#pragma region Example调用实例

//Json相关方法调用实例:
//
// 如果想要调用JsonMaker类来把你的类成员元素,假设是A a,其中包含元素qint32 a1,QString a2,bool a3进行封装,那么你需要使用Q_PROPERTY来
// 声明封装a1,a2,a3元素和其set/get方法(如果需要解析就需要set方法,如果需要封装就需要get方法),set/get方法命名规则为set/get+元素名称
// 比如seta1,geta2,其中不对大小写做规定,也可以写成setA1,getA2
//
// 调用方法如下:
// 1.封装字符串
// A a;
// QString result = JsonMaker::Singleton().JsonSerialization<Tester1>(tester);
// 2.解析字符串
// A a
// JsonMaker::Singleton().JsonDeserialization<Tester1>(a, Json);
// 调用完毕后a中的对应数据都会被Json字符串中的数据覆盖
// //测试解析、封装类举例:
class Tester1 :public QObject {
Q_OBJECT
Q_PROPERTY(QString name READ getName WRITE setname)
Q_PROPERTY(QString like READ getLike WRITE setlike)
Q_PROPERTY(QString birthday READ getBirthday WRITE setbirthday)
//Q_PROPERTY(QString str_public READ str_public,WRITE setStr_public)
Q_PROPERTY(QList<QString> list READ getList WRITE setlist)
Q_PROPERTY(QList<qint32> qint32_list READ getqint32_List WRITE setqint32_list)
//暂时不支持float类型
//Q_PROPERTY(QList<float> float_list READ getFloat_List)
Q_PROPERTY(QList<double> double_list READ getDouble_List WRITE setdouble_list)
Q_PROPERTY(QList<bool> bln_list READ getBln_List WRITE setbln_list)
Q_PROPERTY(QList<int> int_list READ getInt_list WRITE setint_list)
public:
Tester1(QObject* parent = Q_NULLPTR);
//QString str_public = "str_public";
#pragma region get funcs QString getName() {
return name;
}
QString getLike() {
return like;
}
QString getBirthday() {
return birthday;
}
QList<QString> getList() {
return this->list;
}
QList<int> getInt_list() {
return this->int_list;
}
QList<qint32> getqint32_List() {
return this->qint32_list;
}
QList<float> getFlost_List() {
return this->float_list;
}
QList<double> getDouble_List() {
return this->double_list;
}
QList<bool> getBln_List()
{
return this->bln_list;
}
QList<float> getFloat_List() {
return float_list;
}
#pragma endregion #pragma region Set Funcs
/*QList<QString> list = { "123","234","345","4356" };
QList<qint32> qint_list = { 123,234,345,456 };
QList<float> float_list = { 1.123123,2.234234,4.345345,45.457457 };
QList<double> double_list = { 1.2443,3.52,2.351,1.235 };
QList<int> int_list = { 234,345,456,567,678,123,32 };
QList<bool> bln_list = { true,false,true,false };*/ Q_INVOKABLE void setlist(QList<QString> list_value) {
this->list = list_value;
}
Q_INVOKABLE void setqint32_list(QList<qint32> list_value) {
this->qint32_list = list_value;
}
Q_INVOKABLE void setdouble_list(QList<double> list_value) {
this->double_list = list_value;
}
Q_INVOKABLE void setint_list(QList<int> list_value) {
this->int_list = list_value;
}
Q_INVOKABLE void setbln_list(QList<bool> list_value) {
this->bln_list = list_value;
}
Q_INVOKABLE void setname(QString strValue) {
this->name = strValue;
}
Q_INVOKABLE void setlike(QString strValue) {
this->like = strValue;
}
Q_INVOKABLE void setbirthday(QString strValue) {
this->birthday = strValue;
} #pragma endregion private:
QString name = "name";
QString like = "like";
QString birthday = "birthday";
QList<QString> list = { "123","234","345","4356" };
QList<qint32> qint32_list = { 123,234,345,456 };
QList<float> float_list = { 1.123123,2.234234,4.345345,45.457457 };
QList<double> double_list = { 1.2443,3.52,2.351,1.235 };
QList<int> int_list = { 234,345,456,567,678,123,32 };
QList<bool> bln_list = { true,false,true,false };
};
#pragma endregion //Json相关
//给定任意模板类,将其公开属性打包成一个Json字符串,使用此方法需要所有的公开属性均为Q_PROPERTY宏声明,该类提供单例。
//序列化类Q_PROPERTY宏声明的属性 set/get函数命名规则:get/set+属性名 如getBirthday setList,大小写不限,如果是set方法需要在set方法前面加上Q_INVOKABLE 宏
//如果需要反序列化数组,请保证数组中的所有数据结构是同一个类型,否则可能会出错
//注:请尽量使用int不要使用qint32,使用double不要使用float
#pragma region JsonMaker
//JsonMaker类使用方法: //Json相关
//给定任意模板类,将其公开属性打包成一个Json字符串,使用此方法需要所有的公开属性均为Q_PROPERTY宏声明,该类提供单例。
//序列化类Q_PROPERTY宏声明的属性 set/get函数命名规则:get/set+属性名 如getBirthday setList,大小写不限,如果是set方法需要在set方法前面加上Q_INVOKABLE 宏
//如果需要反序列化数组,请保证数组中的所有数据结构是同一个类型,否则可能会出错
//注:请尽量使用int不要使用qint32,使用double不要使用float
class JsonMaker :public QObject {
JsonMaker();
//提供单例
public:
static JsonMaker& JsonMaker::Singleton() {
static JsonMaker Instance;
return Instance;
// TODO: 在此处插入 return 语句
} //序列化类Q_PROPERTY宏声明的属性,如果有数组类型,请使用QList<QSharedPointer>来执行指定操作
template<class T1>
QString JsonSerialization(QSharedPointer<T1>T_Class_1) {
auto T_Class = dynamic_cast<QObject*>(T_Class_1.data());
QJsonObject jsonObject;
//通过元对象定义成员
const QMetaObject* metaObject = T_Class->metaObject();
for (int i = 0; i < metaObject->propertyCount(); ++i) {
QMetaProperty property = metaObject->property(i); if (!property.isReadable()) {
continue;
}
//这个不知道是什么,暂时需要先屏蔽掉 if (QString(property.name()) == "objectName") {
continue;
} //如果是QList if (QString(property.typeName()).contains("QList")) {
//这里可能要根据常见类型进行一下分类
QJsonArray jsonListArray;
//输入一个模板类类型,输出一个jsonObject
if (QString(property.typeName()) == "QList<QString>") {
QList<QString> str_message = property.read(T_Class).value<QList<QString>>();
jsonListArray = QListToJsonArray(str_message);
}
else if (QString(property.typeName()) == "QList<qint32>" || QString(property.typeName()) == "QList<int>") {
QList<qint32> str_message = property.read(T_Class).value<QList<qint32>>();
jsonListArray = QListToJsonArray(str_message);
}
else if (QString(property.typeName()) == "QList<qint64>") {
QList<qint64> str_message = property.read(T_Class).value<QList<qint64>>();
jsonListArray = QListToJsonArray(str_message);
}
else if (QString(property.typeName()) == "QList<int>") {
QList<int> str_message = property.read(T_Class).value<QList<int>>();
jsonListArray = QListToJsonArray(str_message);
}
else if (QString(property.typeName()) == "QList<bool>") {
QList<bool> str_message = property.read(T_Class).value<QList<bool>>();
jsonListArray = QListToJsonArray(str_message);
}
else if (QString(property.typeName()) == "QList<double>") {
QList<double> str_message = property.read(T_Class).value<QList<double>>();
jsonListArray = QListToJsonArray(str_message);
}
else if (QString(property.typeName()) == "QList<Float>") {
QList<float> str_message = property.read(T_Class).value<QList<float>>();
jsonListArray = QListToJsonArray(str_message);
}
else if (QString(property.typeName()) == "QList<QByteArray>") {
QList<QByteArray> str_message = property.read(T_Class).value<QList<QByteArray>>();
jsonListArray = QListToJsonArray(str_message);
} jsonObject.insert(property.name(), QJsonValue(jsonListArray));
}
//如果不是QList
else {
QVariant result = property.read(T_Class);
jsonObject[property.name()] = QJsonValue::fromVariant(property.read(T_Class)); }
qDebug() << property.name();
} QJsonDocument doc(jsonObject);
return doc.toJson(QJsonDocument::Compact);
}
//反序列化类Q_PROPERTY宏声明的属性,如果有数组类型,请使用QList
template<class T>
void JsonDeserialization(QSharedPointer<T> T_Class, const QString& jsonString)
{
auto qobject = dynamic_cast<QObject*>(T_Class.data()); QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8());
QJsonObject jsonObject = doc.object();
// 使用QMetaObject的invokeMethod()函数来调用模板类T的setter函数
const QMetaObject* metaObject = qobject->metaObject(); for (int i = 0; i < metaObject->propertyCount(); ++i) {
QMetaProperty property = metaObject->property(i);
if (property.isReadable() && property.isWritable()) {
QString propertyName = property.name();
QString str_functinoname = QString("set" + propertyName);
//为了转换成const char*类型必须的一个中间步骤
QByteArray temp_qba_functinoname = str_functinoname.toLocal8Bit();
const char* func_name = temp_qba_functinoname.data(); if (jsonObject.contains(propertyName)) {
QJsonValue value = jsonObject[propertyName];
JsonMaker temp;
qDebug() << value;
switch (value.type()) {
case QJsonValue::Type::Bool:
QMetaObject::invokeMethod(qobject, func_name, Q_ARG(bool, value.toBool()));
break;
case QJsonValue::Type::Double:
if (!QMetaObject::invokeMethod(qobject, func_name, Q_ARG(int, value.toDouble())))
QMetaObject::invokeMethod(qobject, func_name, Q_ARG(double, value.toDouble()));
break;
case QJsonValue::Type::String:
qDebug() << QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QString, value.toString()));
break;
case QJsonValue::Type::Array: {
//如果是数组则需要根据情况进行解析
if (!value.isArray()) {
break;
}
QJsonArray arr = value.toArray();
//下面确定数组类型
this->JsonArrayDeserialization(qobject, func_name, arr);
}
break;
case QJsonValue::Type::Object:
QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QJsonValue, value));
break;
default:
break;
}
}
}
}
} private:
//将模板类QList转换成JsonObject
template<class T>
QJsonArray QListToJsonArray(QList<T> list) {
QJsonArray jsonArray;
for each (T temp_T in list)
{
jsonArray.append(QJsonValue::fromVariant(temp_T));
} return jsonArray;
} //解析数组并注入QObject对象
void JsonArrayDeserialization(QObject* qobject, const char* func_name, QJsonArray arr) {
try {
//判断类型
//QString
if (arr[0].type() == QJsonValue::String) {
QList<QString> list_result;
QJsonValue value; for each (QJsonValue temp_value in arr)
{
list_result.append(temp_value.toString());
}
QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QList<QString>, list_result)); }
else if (arr[0].isDouble()) {
//若为为整形
if (arr[0].toDouble() == arr[0].toInt()) {
qDebug() << arr[0].toDouble() << arr[0].toInt();
QList<qint32> list_result;
QList<int> list_result_2;
QJsonValue value; for each (QJsonValue temp_value in arr)
{
//int 和 qint32都需要尝试,但请尽量尝试使用qint32,这段代码占用了两倍的内存,将来可能考虑删除
list_result.append(temp_value.toInt());
list_result_2.append(temp_value.toInt());
}
if (!QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QList<qint32>, list_result))) {
QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QList<int>, list_result_2));
}
}
//若为双精度
else {
QList<double> list_result;
QList<float> list_result_2;
QJsonValue value; for each (QJsonValue temp_value in arr)
{
list_result.append(temp_value.toDouble());
}
//double和float都会尝试,请尽量使用double
if (!QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QList<double>, list_result))) {
QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QList<float>, list_result_2));
} }
}if (arr[0].type() == QJsonValue::Bool) {
QList<bool> list_result;
QJsonValue value; for each (QJsonValue temp_value in arr)
{
list_result.append(temp_value.toBool());
}
QMetaObject::invokeMethod(qobject, func_name, Q_ARG(QList<bool>, list_result));
}
}
catch (const QException& e) {
WriteErrorMessage("JsonArrayDeserialization", "JsonArrayDeserialization", e.what());
}
} };
#pragma endregion

【QtJson】用Qt自带的QJson,直接一步到位封装和解析一个类的实例对象!的更多相关文章

  1. Qt使用com组件的一点小心得(使用Qt自带的工具dumpcpp生成.h和.cpp文件)

    这几天工作中要用到Qt调用com组件,主要用到的类型有dll和ocx,使用他们的方法很简单:1.将com组件注册到系统中.2.使用Qt自带的工具dumpcpp将com组件生成cpp和头文件.3.然后就 ...

  2. Qt平台下使用QJson解析和构建JSON字符串

    前言 上一篇介绍了C语言写的JSON解析库cJSON的使用:使用cJSON库解析和构建JSON字符串 本篇文章介绍,Qt开发环境下QJson库的使用示例,JSON解析配合API接口,就可以实现一些有趣 ...

  3. Qt5.6使用Qt自带虚拟键盘

    Qt自带虚拟键盘是5.7版本以上才有,要在Qt5.6上使用自带虚拟键盘需要先下载源码,再进行编译安装.上网查了一些资料都很有用. https://doc.qt.io/qt-5/qtvirtualkey ...

  4. Blocking Master Example QT 自带 的 serial 即 串口 例子

    1.官方解释文档:http://doc.qt.io/qt-5/qtserialport-blockingmaster-example.html Blocking Master shows how to ...

  5. PyQt(Python+Qt)入门:Designer组件属性编辑界面中QWidget类相关属性详解

    本文适用人员:本文比较长,适合不理解Qt Designer部件属性的人员阅读或资料查找. 声明: 1.如果有人认为本文是简单的复制粘贴+翻译而成,敬请读本文最后的后记: 2.本文为老猿Python学习 ...

  6. Qt信号槽机制的实现(面试的感悟,猜测每一个类保存的一个信号和槽的二维表,实际使用函数指针 元对象 还有类型安全的检查设定等等)

    因为面试时问了我这道题,导致我想去了解信号槽到底是如何实现的,于是贴着顺序看了下源码,大致了解了整个框架.网上关于信号槽的文章也很多,但是大部分都是将如何应用的,这里我就写一下我所理解的如何实现吧, ...

  7. 学习懈怠的时候,可以运行Qt自带的Demo,或者Delphi控件自带的Demo,或者Cantu书带的源码,运行一下Boost的例子(搞C++不学习Boost/Poco/Folly绝对是一大损失,有需要使用库要第一时间想到)(在六大的痛苦经历说明,我的理论性确实不强,更适合做实践)

    这样学还不用动脑子,而且熟悉控件也需要时间,而且慢慢就找到感觉了,就可以精神抖擞的恢复斗志干活了.或者Cantu书带的源码. 并且可以使用Mac SSD运行Qt的Demo,这样运行速度快一点. 此外, ...

  8. Qt封装QTcpServer参考资料--QT自带QTcpServer架构分析

    Qt 4.6自带的threaddedfortuneserver是个简单明了的 Qt  C/S网络编程server端程序的例子, 该例子演示了 QTcpServer与QThread配合的方法. 代码不多 ...

  9. Qt自带的阴影类、跨线程问题汇总、hover相关、全屏轮子,一些思考。

    一点思考:故事的结局重不重要? 我语文不好,但是我数学不好. 我数学不好,但是我英语不好. 我英语不好,但是我物理不好. 我物理不好,但是我化学不好. 我化学不好,但是我历史不好. 我历史不好,但是我 ...

  10. Qt自定义带游标的slider,在滑块正上方显示当前值(类似于进度条,用一个额外的QLabel冒充QSilder的一部分,然后move就行了)

    首先自定义QSlider的子类MyCustomSlider,如下所示. mycustomslider.h #ifndef MYCUSTOMSLIDER_H #define MYCUSTOMSLIDER ...

随机推荐

  1. 文心一言 VS 讯飞星火 VS chatgpt (154)-- 算法导论12.3 1题

    一.用go语言,给出 TREE-INSERT 过程的一个递归版本. 文心一言,代码不能运行: 下面是用 Go 语言实现一个递归版本的 TREE-INSERT 过程的代码: package main i ...

  2. C#Socket编程详解(一)TCP与UDP简介

    一.TCP与UDP(转载) 1.TCP 1.1 定义 TCP(TransmissionControl Protocol)传输控制协议. 是一种可靠的.面向连接的协议(eg:打电话).传输效率低全双工通 ...

  3. parameterType的用法

    在mybatis映射接口的配置中,有select,insert,update,delete等元素都提到了parameterType的用法,parameterType为输入参数,在配置的时候,配置相应的 ...

  4. 国家专用加密数据传输之rsa,3des加密方法-rasor3desc

    title: 国家专用加密数据传输之rsa,3des加密方法 date: 2021-12-20 13:08:21.646 updated: 2022-03-10 16:00:58.65 url: ht ...

  5. 【电影推荐系统】Spring Boot + Vue3 前后端分离项目

    目录 0 前言 1 项目前端介绍 1.1 项目启动和编译 1.1.1 项目启动 1.1.2 项目编译 1.2 前端技术栈 1.3 功能模块前端界面展示 1.3.1 基础功能模块 1.3.2 用户模块 ...

  6. Socket.D 替代 Http 协议像 Ajax 一样开发前端接口

    我们在"前端接口"开发时,使用 socket.d 协议有什么好处: 功能上可以替代 http 和原生 ws 更安全!现有的工具想抓包数据,难!难!难!(socket.d 是个新的二 ...

  7. 放弃JavaFx开发学习

    放弃JavaFx开发学习 一开始学学习JavaFx是想用java写个小游戏,后来学者JavaFx越来越深,发现坑也越来越多,不禁感叹:JavaFx果然是要抛弃的UI玩儿,UI开发还是用react na ...

  8. 27、flutter Dialog 弹窗

    AlertDialog //放在State<>之下 void _alertDialog() async { var result = await showDialog( barrierDi ...

  9. 数据安全无小事:揭秘华为云GaussDB(openGauss)全密态数据库

    摘要:全密态数据库,专门处理密文数据的数据库系统,数据以加密形态存储在数据库服务器中,数据库支持对密文数据的检索与计算. 1.云数据库安全现状及问题 伴随着云基础设施的快速增长和成熟,与之对应的云数据 ...

  10. MRS离线数据分析:通过Flink作业处理OBS数据

    摘要:MRS支持在大数据存储容量大.计算资源需要弹性扩展的场景下,用户将数据存储在OBS服务中,使用MRS集群仅做数据计算处理的存算分离模式. 本文分享自华为云社区<[云小课]EI第47课 MR ...