【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 ...
随机推荐
- java协程操作mysql数据库
我的项目: nanshaws/nettyWeb: 复习一下netty,并打算做一个web项目出来 (github.com) 最近在项目中分别添加了虚拟线程操作mysql数据库,和用协程操作mysql数 ...
- Codeforces-470 div2 C题
C. Producing Snow time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- Using PostMessage/SendMessage to send keys to c# IE WebBrowser
[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool PostM ...
- 如何使用Redisson实现分布式锁?
在分布式系统中,当多个线程(或进程)同时操作同一个资源时,为了保证数据一致性问题,所以就需要一种机制来确保在同一时间只有一个线程(或进程)能够对资源进行修改,这就是分布式锁的作用. 分布式锁是一种在分 ...
- Huggy Lingo: 利用机器学习改进 Hugging Face Hub 上的语言元数据
太长不看版: Hub 上有不少数据集没有语言元数据,我们用机器学习来检测其语言,并使用 librarian-bots 自动向这些数据集提 PR 以添加其语言元数据. Hugging Face Hub ...
- 6.elasticsearch中search template和alias
什么是search template 顾名思义,查询模版,就是提前设定好查询的DSL,再次查询时,只需要指定对应的模版,然后传入相应的参数就好.一是可以每次不用构建复杂的DSL,二是可以供开发直接使用 ...
- mysql将查询结果生成临时表
MySQL中将查询的结果生成临时表,列类型与查询的列一致,百度搜索到的没啥用. 直接上SQL: 将结果生成临时表 create temporary table temp_tb_name as (sel ...
- JavaFx之使用高版本JDK(二十八)
JavaFx之使用高版本JDK(二十八) 如何使用高版本的jfx? 根据官网的需要手动引入jfx模块(运行参数:–module-path) 要知道高版本jfx已经集成了丰富的主流功能,例如视频编码,大 ...
- C#中对比两个对象是否相等最佳实践,IEquatable和IEqualityComparer的差异
前言 IEquatable<T> IEqualityComparer<T> 后言 参考 前言 IEquatable<T> 和 IEqualityComparer&l ...
- JavaImprove--Lesson02--Object类,Objects工具类,封装类
一.Object类 Java中的Object类是所有类的超类,它是Java类层次结构的根类.这意味着所有的类都直接或间接地继承自Object类 equals(Object obj): 用于比较两个对象 ...