【QtJson】用Qt自带的QJson,直接一步到位封装和解析一个类的实例对象!
之前貌似没有看过类似的代码
我们现在的要求就是直接在不知道类成员的情况下,把一个类丢进去就能生成一个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,直接一步到位封装和解析一个类的实例对象!的更多相关文章
- Qt使用com组件的一点小心得(使用Qt自带的工具dumpcpp生成.h和.cpp文件)
这几天工作中要用到Qt调用com组件,主要用到的类型有dll和ocx,使用他们的方法很简单:1.将com组件注册到系统中.2.使用Qt自带的工具dumpcpp将com组件生成cpp和头文件.3.然后就 ...
- Qt平台下使用QJson解析和构建JSON字符串
前言 上一篇介绍了C语言写的JSON解析库cJSON的使用:使用cJSON库解析和构建JSON字符串 本篇文章介绍,Qt开发环境下QJson库的使用示例,JSON解析配合API接口,就可以实现一些有趣 ...
- Qt5.6使用Qt自带虚拟键盘
Qt自带虚拟键盘是5.7版本以上才有,要在Qt5.6上使用自带虚拟键盘需要先下载源码,再进行编译安装.上网查了一些资料都很有用. https://doc.qt.io/qt-5/qtvirtualkey ...
- Blocking Master Example QT 自带 的 serial 即 串口 例子
1.官方解释文档:http://doc.qt.io/qt-5/qtserialport-blockingmaster-example.html Blocking Master shows how to ...
- PyQt(Python+Qt)入门:Designer组件属性编辑界面中QWidget类相关属性详解
本文适用人员:本文比较长,适合不理解Qt Designer部件属性的人员阅读或资料查找. 声明: 1.如果有人认为本文是简单的复制粘贴+翻译而成,敬请读本文最后的后记: 2.本文为老猿Python学习 ...
- Qt信号槽机制的实现(面试的感悟,猜测每一个类保存的一个信号和槽的二维表,实际使用函数指针 元对象 还有类型安全的检查设定等等)
因为面试时问了我这道题,导致我想去了解信号槽到底是如何实现的,于是贴着顺序看了下源码,大致了解了整个框架.网上关于信号槽的文章也很多,但是大部分都是将如何应用的,这里我就写一下我所理解的如何实现吧, ...
- 学习懈怠的时候,可以运行Qt自带的Demo,或者Delphi控件自带的Demo,或者Cantu书带的源码,运行一下Boost的例子(搞C++不学习Boost/Poco/Folly绝对是一大损失,有需要使用库要第一时间想到)(在六大的痛苦经历说明,我的理论性确实不强,更适合做实践)
这样学还不用动脑子,而且熟悉控件也需要时间,而且慢慢就找到感觉了,就可以精神抖擞的恢复斗志干活了.或者Cantu书带的源码. 并且可以使用Mac SSD运行Qt的Demo,这样运行速度快一点. 此外, ...
- Qt封装QTcpServer参考资料--QT自带QTcpServer架构分析
Qt 4.6自带的threaddedfortuneserver是个简单明了的 Qt C/S网络编程server端程序的例子, 该例子演示了 QTcpServer与QThread配合的方法. 代码不多 ...
- Qt自带的阴影类、跨线程问题汇总、hover相关、全屏轮子,一些思考。
一点思考:故事的结局重不重要? 我语文不好,但是我数学不好. 我数学不好,但是我英语不好. 我英语不好,但是我物理不好. 我物理不好,但是我化学不好. 我化学不好,但是我历史不好. 我历史不好,但是我 ...
- Qt自定义带游标的slider,在滑块正上方显示当前值(类似于进度条,用一个额外的QLabel冒充QSilder的一部分,然后move就行了)
首先自定义QSlider的子类MyCustomSlider,如下所示. mycustomslider.h #ifndef MYCUSTOMSLIDER_H #define MYCUSTOMSLIDER ...
随机推荐
- 【问题解决】unable to do port forwarding: socat not found
问题复现 前阵子应公司要求做华为云平台的调研,写了一篇文档包含将华为云CCE下载kuberctl配置及使用kubectl转发流量到本地的操作. 今天一早上同事就发来一个错误界面,说是Java远程调试转 ...
- MySQL运维11-Mycat分库分表之应用指定分片
一.应用指定分片 此规则是在运行阶段有应用自主决定路由到那个分片,根据提供的字段,然后按照指定的规则,截取该字段的部分子字符串当做分片的依据,该分别方法比较灵活,适用于某个字段有几个特殊的字符串拼接而 ...
- LeetCode1806:还原排列的最少操作步数(置换群 or 模拟)
题意:题目的意思是,给定一个初始状态perm,然后对perm的每个元素按照上述的规则进行变换操作.问:perm经过多少次这种操作能够变回初始的perm. 解题思路:第一种方法就是模拟,一直变换,直到变 ...
- 牛客小白月赛2 E题 是是非非 (尼姆博弈)
题目链接:https://www.nowcoder.com/acm/contest/86/E 解题思路:由尼姆博弈我们可以知道,如果所有堆的石子数量异或为0,那么先手必败,否则先手必胜. 由异或我们可 ...
- 华企盾DSC邮件服务器测试连接提示Bad login or password(账号密码错误)
解决方法:出现该提示说明账号和密码有一个填错了,注意:这里的密码不是邮箱本身的密码,是授权码,具体可以在邮箱设置中查看,而且必须开启smtp服务才能正常使用.
- NetSuite 开发日记:批量增删改
一.批量插入/创建 使用 record.create() 插入数据时,一次只能插入一条,有多条数据需要插入时只能通过循环的方式,这样效率非常慢,耗时会随着数据量的增大而呈线性增长,有一种巧妙的方式可以 ...
- MinIO客户端之mv
MinIO提供了一个命令行程序mc用于协助用户完成日常的维护.管理类工作. 官方资料 mc mv 将对象在桶之间移动. 在桶内准备好待移动的文件,检查对象,命令如下: ./mc ls local1/b ...
- ElasticSearch之配置
ElasticSearch主要的配置文件,如下: elasticsearch.yml,ElasticSearch的相关参数. jvm.options,JVM的相关参数. log4j2.properti ...
- Guava Cache 异步刷新技巧,你值得拥有!
Guava Cache是一款非常优秀的本地缓存框架,提供简洁易用的 API 供开发者使用. 这篇文章,我们聊聊如何使用 Guava Cache 异步刷新技巧带飞系统性能 . 1 基本用法 首先,在 J ...
- 玩转Python:处理音频文件,两个非常重要的库,很实用,附代码
pyaudio和sounddevice都是用于Python中音频处理和流的库,允许用户通过他们的API录制.播放和处理音频数据.下面是对这两个库的简要介绍: PyAudio PyAudio 提供了 P ...