五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(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ā)中的應用(二)的評論 (共 條)

分享到微博請遵守國家法律
石河子市| 张家界市| 嘉祥县| 永年县| 沂水县| 永胜县| 南溪县| 武冈市| 泗水县| 基隆市| 盐源县| 枝江市| 洪泽县| 修水县| 红安县| 闽侯县| 会昌县| 乐业县| 菏泽市| 丹东市| 武山县| 大厂| 渑池县| 栾川县| 交城县| 兰溪市| 讷河市| 新巴尔虎右旗| 巴彦县| 浦城县| 泸水县| 同江市| 太原市| 江北区| 南和县| 化州市| 汽车| 琼结县| 银川市| 广水市| 团风县|