最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

C++自動序列化和反序列化在實際軟件開發(fā)中的應用(二)

2023-09-04 23:41 作者:devstone  | 我要投稿

上一篇文章介紹了自動進行序列化和反序列化的方法,其中也指出了其中存在的問題以及不足,今天這篇文章來詳細說下如何處理

背景

目前使用自動生成屬性的方法支持的數(shù)據(jù)類型有限,并不是所有的數(shù)據(jù)類型有支持,不支持的類型生成的鍵值對的值會是 null,肯定不是我們想要的,因此需要對這些類型進行自定義擴展。

目前不支持的類型主要有以下幾種場景:

  • QRect

  • QSize

  • QPoint

  • QList<T>,QVector<T>,比如: QList<int>,QList<float>,QList<double>……

  • QPolygon, QPolygonF

  • QLine,QLineF

  • QMap, QSet,QHash……

  • std 標準庫數(shù)據(jù)類型

  • 其它自定義類型

原因

為什么上述類型不支持呢?有兩個原因:

第一,上述這些類型無法反向解析,無法進行有效的區(qū)分,比如你想把一個QSize 保存成什么樣子?

  • 數(shù)組形式:[10,10]

  • 字符串:"QSize(10,10)"

不管哪種方式,都不是通用的,數(shù)組格式在反序列化時無法還原,除非手動進行,字符串方式有冗余字段無法滿足三方使用。

第二,其實不怪 Qt,JSON 的鍵值就支持這些類型,[侯捷] 曾說過「源碼面前了無秘密」,我們再順便看下Qt源碼。

某個字段的值是這樣獲取的,返回的是一個 QVariant 類型,這個類型本身可以支持多種數(shù)據(jù)類型

QVariant?v?=?object->property(proName);

將獲取的鍵值插入到 QJsonObject 當中:

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

問題就出在這里,JSON 對象的值需要一個 QJsonValue 類型,但是 QJsonValue 僅僅支持常見的基本數(shù)據(jù)類型

????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);

基于上述兩個原因,我們能夠做的只能是把其它類型轉(zhuǎn)換成標準JSON 支持的類型。

方案

JSON作為通用的數(shù)據(jù)格式,一般普遍做法需要針對特殊類型字段單獨處理,再反序列化時也需要單獨處理,下面以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 是類似的,因此需要寫一個模板來統(tǒng)一處理:

template?<class?Size>
static?inline?QVariant?serializeSize(const?Size?&size)
{

????return?QVariant(QJsonArray{size.width(),?size.height()});
}

擴展

一般我們能想到的是分別實現(xiàn)對QSizeQSizeF 進行處理,這個時候你會寫兩個函數(shù)來處理,進階后你會寫一個模板來處理,那么再次進階下,怎么處理呢?

來看一個更高級的用法(語法糖,C++17才有的)

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

上述代碼可以參考開源項目: https://github.com/Skycoder42/QtJsonSerializer

總結(jié)

上述提供了一種方案和思路,按照這個思路繼續(xù)擴展其它數(shù)據(jù)類型即可,如果感興趣可以直接看這個開源項目:https://github.com/Skycoder42/QtJsonSerializer, 不過需要 Qt5.12 及以上版本才支持哦

如果想自己動手實現(xiàn),順便深入學習下 Qt 元對象系統(tǒng),那么可以一起參與進來,從零實現(xiàn)一個簡易版本的序列化庫: https://github.com/kevinlq/KSerialize.

授人以魚不如授人以漁, 方案和思路有了,關鍵還是要多動手寫起來,如果有問題隨時留言交流。


C++自動序列化和反序列化在實際軟件開發(fā)中的應用(二)的評論 (共 條)

分享到微博請遵守國家法律
浏阳市| 景宁| 周口市| 临桂县| 海盐县| 汨罗市| 东明县| 枝江市| 绥滨县| 凤台县| 怀宁县| 杂多县| 汨罗市| 安乡县| 榆社县| 郓城县| 孝昌县| 岑巩县| 巴南区| 井研县| 蒙自县| 桦南县| 庄河市| 安吉县| 龙岩市| 玉林市| 元江| 新建县| 遵义市| 西青区| 黄大仙区| 温州市| 龙海市| 桃源县| 庐江县| 英超| 昭苏县| 柳江县| 建阳市| 夏邑县| 石嘴山市|