C++自动序列化和反序列化在实际软件开发中的应用(二)

上一篇文章介绍了自动进行序列化和反序列化的方法,其中也指出了其中存在的问题以及不足,今天这篇文章来详细说下如何处理

背景

目前使用自动生成属性的方法支持的数据类型有限,并不是所有的数据类型有支持,不支持的类型生成的键值对的值会是 null,肯定不是我们想要的,因此需要对这些类型进行自定义扩展。

目前不支持的类型主要有以下几种场景:

  • QRect
  • QSize
  • QPoint
  • QList<T>,QVector<T>,比如: QList<int>,QList<float>,QList<double>……
  • QPolygon, QPolygonF
  • QLine,QLineF
  • QMap, QSet,QHash……
  • std 标准库数据类型
  • 其它自定义类型

原因

为什么上述类型不支持呢?有两个原因:

第一,上述这些类型无法反向解析,无法进行有效的区分,比如你想把一个QSize 保存成什么样子?

  • 数组形式:[10,10]
  • 字符串:“QSize(10,10)”

不管哪种方式,都不是通用的,数组格式在反序列化时无法还原,除非手动进行,字符串方式有冗余字段无法满足三方使用。

第二,其实不怪 QtJSON 的键值就支持这些类型,[侯捷] 曾说过「源码面前了无秘密」,我们再顺便看下Qt源码。

某个字段的值是这样获取的,返回的是一个 QVariant 类型,这个类型本身可以支持多种数据类型

QVariant v = object->property(proName);

将获取的键值插入到 QJsonObject 当中:

jsObj.insert(proName, QJsonValue::fromVariant(v));

问题就出在这里,JSON 对象的值需要一个 QJsonValue 类型,但是 QJsonValue 仅仅支持常见的基本数据类型

    QJsonValue(Type = Null);QJsonValue(bool b);QJsonValue(double n);QJsonValue(int n);QJsonValue(qint64 v);QJsonValue(const QString &s);QJsonValue(QLatin1String s);QJsonValue(const QJsonArray &a);QJsonValue(const QJsonObject &o);

基于上述两个原因,我们能够做的只能是把其它类型转换成标准JSON 支持的类型。

方案

JSON作为通用的数据格式,一般普遍做法需要针对特殊类型字段单独处理,再反序列化时也需要单独处理,下面以QPoint、QSize 两种类型为例详细展开说下:

    Q_PROPERTY(QSize testSize READ testSize WRITE setTestSize)Q_PROPERTY(QPoint testPoint READ testPoint WRITE setTestPoint)

在进行序列化时,判断该属性类型,然后分别进行处理:

    switch (propertyType){case QMetaType::QSize:      return serializeSize(value.toSize());case QMetaType::QSizeF:     return serializeSize(value.toSizeF());default:                    throw  KException{ QByteArray("Invalid type id ") +QByteArray(QMetaType::typeName(propertyType))};}

QSize和QSizeF 是类似的,因此需要写一个模板来统一处理:

template <class Size>
static inline QVariant serializeSize(const Size &size)
{return QVariant(QJsonArray{size.width(), size.height()});
}

扩展

一般我们能想到的是分别实现对QSizeQSizeF 进行处理,这个时候你会写两个函数来处理,进阶后你会写一个模板来处理,那么再次进阶下,怎么处理呢?

来看一个更高级的用法(语法糖,C++17才有的)

QJsonValue serializeSize(const std::variant<QSize, QSizeF> &size) const
{returnstd::visit([](const auto &s) -> QJsonArray {return {s.width(), s.height()};}, size);
}

上述代码可以参考开源项目: https://github.com/Skycoder42/QtJsonSerializer

总结

上述提供了一种方案和思路,按照这个思路继续扩展其它数据类型即可,如果感兴趣可以直接看这个开源项目:https://github.com/Skycoder42/QtJsonSerializer, 不过需要 Qt5.12 及以上版本才支持哦

如果想自己动手实现,顺便深入学习下 Qt 元对象系统,那么可以一起参与进来,从零实现一个简易版本的序列化库: https://github.com/kevinlq/KSerialize.

授人以鱼不如授人以渔, 方案和思路有了,关键还是要多动手写起来,如果有问题随时留言交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/69924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现SSE的textevent-stream是什么?和applicationoctet-stream有什么区别?

WEB通讯技术。前端实现SSE长连接&#xff0c;nodejsexpress搭建简单服务器&#xff0c;进行接口调试&#xff0c;通过curl请求数据 点击上面的地址是可以了解轮询和长轮询以及websocket等通信模式&#xff0c;一些基础概念和速成技能&#xff0c;这篇来接着详细聊聊text/event…

Qt---对话框 事件处理 如何发布自己写的软件

目录 一、对话框 1.1 消息对话框&#xff08;QMessageBox&#xff09; 1> 消息对话框提供了一个模态的对话框&#xff0c;用来提示用户信息&#xff0c;或者询问用户问题并得到回答 2> 基于属性版本的API 3> 基于静态成员函数版本 4> 对话框案例 1、ui界面 …

Direct3D光照

光照的组成 环境光&#xff1a;这种类型的光经其他表面反射到达物体表面&#xff0c;并照亮整个场景&#xff0c;要想以较低代价粗略模拟这类反射光&#xff0c;环境光是一个很好的选择 漫射光&#xff1a;这种类型光沿着特定的方向传播。当它到达某一表面时&#xff0c;将沿…

2023年8月30日-[SWPUCTF 2021 新生赛]jicao

<?php highlight_file(index.php); include("flag.php"); $id$_POST[id]; $jsonjson_decode($_GET[json],true); if ($id"wllmNB"&&$json[x]"wllm") {echo $flag;} ?> 包含了flag.php文件&#xff0c;设定了一个POST请求的id和…

【AIGC专题】Stable Diffusion 从入门到企业级实战0401

一、概述 本章是《Stable Diffusion 从入门到企业级实战》系列的第四部分能力进阶篇《Stable Diffusion ControlNet v1.1 图像精准控制》第01节&#xff0c; 利用Stable Diffusion ControlNet Inpaint模型精准控制图像生成。本部分内容&#xff0c;位于整个Stable Diffusion生…

Ubuntu之apt-get系列--apt-get安装软件的方法/教程

原文网址&#xff1a;Ubuntu之apt-get系列--apt-get安装软件的方法/教程_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Ubuntu使用apt-get安装软件的方法。 安装软件 先更新列表 sudo apt-get update 安装软件 sudo apt-get install <package name>[<version>]…

Android后退堆栈

修改代码 现在的ItemClick使得用户单击其中一个项目时就会跳转&#xff0c;现在要修改其使得在一个小屏幕设备上才会这样做&#xff0c;在一个大屏幕设备上运行用户选择一个训练项目时在右边的片段显示响应的信息。 希望片段处理后退的方式&#xff1a;假设用户在手机上运行这…

MySQL 50 题。

MySQL 50 题。 文章目录 MySQL 50 题。数据库。sql。 数据库。 CREATE SCHEMA new_schema DEFAULT CHARACTER SET utf8mb4 ;Operation failed: There was an error while applying the SQL script to the database. Executing: CREATE SCHEMA new_schema DEFAULT CHARACTER SE…

【ES6】js中的__proto__和prototype

在JavaScript中&#xff0c;__proto__和prototype都是用于实现对象继承的关键概念。 1、proto __proto__是一个非标准的属性&#xff0c;用于设置或获取一个对象的原型。这个属性提供了直接访问对象内部原型对象的途径。对于浏览器中的宿主对象和大多数对象来说&#xff0c;可…

单例模式——C++版本

1.什么是单例模式 在一个项目中&#xff0c;全局范围内&#xff0c;某个类的实例有且仅有一个&#xff0c;通过这个唯一实例向其他模块提供数据的全局访问&#xff0c;这种模式就叫单例模式。 类中多对象的操作函数有如下几个&#xff1a; 构造函数 &#xff1a; 能够创建出一…

加强版python连接飞书通知——本地电脑PC端通过网页链接打开本地已安装软件(调用注册表形式,以漏洞扫描工具AppScan为例)

前言 如果你想要通过超链接来打开本地应用,那么你首先你需要将你的应用添入windows注册表中(这样网页就可以通过指定代号来调用程序),由于安全性的原因所以网页无法直接通过输入绝对路径来调用本地文件。 一、通过创建reg文件自动配置注册表 创建文本文档,使用记事本打开…

STM32使用FAT文件系统-常见概念、代码走读

fat文件系统的所有外部接口都在ff.h中 格式化 挂载 使用文件系统的第一步&#xff0c;就是挂载。 函数原型&#xff1a;FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ static FATFS fs; FRESULT fres f_mo…

【爬虫】7.4. 字体反爬案例分析与爬取实战

字体反爬案例分析与爬取实战 文章目录 字体反爬案例分析与爬取实战1. 案例介绍2. 案例分析3. 爬取 本节来分析一个反爬案例&#xff0c;该案例将真实的数据隐藏到字体文件里&#xff0c;即使我们获取了页面源代码&#xff0c;也无法直接提取数据的真实值。 1. 案例介绍 案例网…

第2节-PhotoShop基础课程-基础操作

文章目录 前言一、详细操作1. 新建 Ctrl N2.打开 Ctrl o1.拖入同一个文件2.打开另外一个文件 3. 首选项 提高软件运行效率 Ctrl K1. 选择ps界面颜色2.文件处理3. 内存以及回操4.暂存位置2. 另存为 Ctrl Shift S3.导出为 Ctrl Alt Shift w 5. 关闭1. 关闭Ctrl W 6. 选择7…

存储过程报Illegal mix of collations错误的解决方法

CREATE PROCEDURE maxAgeStudent(IN _gender CHAR) BEGINDECLARE maxage INT DEFAULT 0;SELECT max(age) INTO maxage FROM student where gender _gender;SELECT * from student WHERE age maxage and gender _gender; END; 在调用的时候 call maxAgeStudent(1) 产生了报…

SpringCloud入门实战(十五)分布式事务框架Seata简介

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…

利用梯度下降法求最小值及动画展示

视频讲解链接:3.1梯度下降法求最小值_哔哩哔哩_bilibili# 利用梯度下降法求最小值 import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation import numpy as np plt.rcParams[font.sans-serif] = [SimHei] # 用来正常显示中文标签 plt.rcParams[ax…

qemu/kvm学习笔记

qemu/kvm架构 cpu虚拟化的示例 Reference: kvmtest.c [LWN.net] 主要步骤&#xff1a; QEMU通过/dev/kvm设备文件发起KVM_CREATE_VM ioctl&#xff0c;请求KVM创建一个虚拟机。KVM创建虚拟机相应的结构体&#xff0c;并为QEMU返回一个虚拟机文件描述符QEMU通过虚拟机文件描述…

学习设计模式之代理模式,但是宝可梦

前言 作者在准备秋招中&#xff0c;学习设计模式&#xff0c;做点小笔记&#xff0c;用宝可梦为场景举例&#xff0c;有错误欢迎指出。 代码同步更新到 github ,要是点个Star您就是我的神 目录 前言代理模式1.情景模拟1.1静态代理优点局限 1.2 动态代理 2.应用3.局限4.解决方…

读懂AUTOSAR,之CAN Driver L-PDU发送和“重入问题”

1. L-PDU发送 L-PDU传输时,Can模块将L-PDU内容ID和数据长度转换为硬件特定格式(如果需要),并触发传输。 [SWS_Can_00059] CAN到内存的数据映射定义为首先发送的CAN数据字节为数组元素0,最后发送的CAN数据字节为数组元素7或63(在CAN FD的情况下)。(SRS_SPAL_12063)[S…