Qt使用Json的項(xiàng)目實(shí)踐
JSON介紹
Qt支持處理JSON數(shù)據(jù)。JSON是一種對(duì)源自Javascript的對(duì)象數(shù)據(jù)進(jìn)行編碼的格式,但現(xiàn)在被廣泛用作互聯(lián)網(wǎng)上的數(shù)據(jù)交換格式。
Qt中的JSON支持提供了一個(gè)易于使用的C++API來(lái)解析、修改和保存JSON數(shù)據(jù)。它還支持以二進(jìn)制格式保存數(shù)據(jù),這種格式可以直接“mmap”,并且訪問(wèn)速度非???。
主要使用的類
Json 類 | 介紹 |
---|---|
QJsonDocument | 它封裝了一個(gè)完整的 JSON 文檔,并且可以從 UTF-8 編碼的基于文本的表示以及 Qt 自己的二進(jìn)制格式讀取和寫(xiě)入該文檔。 |
QJsonArray | JSON 數(shù)組是一個(gè)值列表。可以通過(guò)從數(shù)組中插入和刪除 QJsonValue 來(lái)操作該列表。 |
QJsonObject | JSON 對(duì)象是鍵值對(duì)的列表,其中鍵是唯一的字符串,值由 QJsonValue 表示。 |
QJsonValue | 該類封裝了 JSON 支持的數(shù)據(jù)類型。 |
QJsonValue
在 Qt 中 QJsonValue
可以封裝的基礎(chǔ)數(shù)據(jù)類型有六種(和 Json 支持的類型一致),分別為:
- 布爾類型:QJsonValue::Bool
- 浮點(diǎn)類型(包括整形): QJsonValue::Double
- 字符串類型: QJsonValue::String
- Json 數(shù)組類型: QJsonValue::Array
- Json 對(duì)象類型:QJsonValue::Object
- 空值類型: QJsonValue::Null
這些類型可以通過(guò) QJsonValue 的構(gòu)造函數(shù)被封裝為一個(gè)類對(duì)象:
// Json對(duì)象 QJsonValue(const QJsonObject &o); // Json數(shù)組 QJsonValue(const QJsonArray &a); // 字符串 QJsonValue(const char *s); QJsonValue(QLatin1String s); QJsonValue(const QString &s); // 整形 and 浮點(diǎn)型 QJsonValue(qint64 v); QJsonValue(int v); QJsonValue(double v); // 布爾類型 QJsonValue(bool b); // 空值類型 QJsonValue(QJsonValue::Type type = Null);
如果我們得到一個(gè) QJsonValue
對(duì)象,如何判斷內(nèi)部封裝的到底是什么類型的數(shù)據(jù)呢?這時(shí)候就需要調(diào)用相關(guān)的判斷函數(shù)了,具體如下:
// 是否是Json數(shù)組 bool isArray() const; // 是否是Json對(duì)象 bool isObject() const; // 是否是布爾類型 bool isBool() const; // 是否是浮點(diǎn)類型(整形也是通過(guò)該函數(shù)判斷) bool isDouble() const; // 是否是空值類型 bool isNull() const; // 是否是字符串類型 bool isString() const; // 是否是未定義類型(無(wú)法識(shí)別的類型) bool isUndefined() const;
通過(guò)判斷函數(shù)得到對(duì)象內(nèi)部數(shù)據(jù)的實(shí)際類型之后,如果有需求就可以再次將其轉(zhuǎn)換為對(duì)應(yīng)的基礎(chǔ)數(shù)據(jù)類型,對(duì)應(yīng)的 API 函數(shù)如下:
// 轉(zhuǎn)換為Json數(shù)組 QJsonArray toArray(const QJsonArray &defaultValue) const; QJsonArray toArray() const; // 轉(zhuǎn)換為布爾類型 bool toBool(bool defaultValue = false) const; // 轉(zhuǎn)換為浮點(diǎn)類型 double toDouble(double defaultValue = 0) const; // 轉(zhuǎn)換為整形 int toInt(int defaultValue = 0) const; // 轉(zhuǎn)換為Json對(duì)象 QJsonObject toObject(const QJsonObject &defaultValue) const; QJsonObject toObject() const; // 轉(zhuǎn)換為字符串類型 QString toString() const; QString toString(const QString &defaultValue) const;
QJsonObject
QJsonObject
封裝了 Json
中的對(duì)象,在里邊可以存儲(chǔ)多個(gè)鍵值對(duì),為了方便操作,鍵值為字符串類型,值為 QJsonValue
類型。
- 如何創(chuàng)建空的 Json 對(duì)象
QJsonObject::QJsonObject(); // 構(gòu)造空對(duì)象
- 將鍵值對(duì)添加到空對(duì)象中
iterator QJsonObject::insert(const QString &key, const QJsonValue &value);
- 獲取對(duì)象中鍵值對(duì)個(gè)數(shù)
int QJsonObject::count() const; int QJsonObject::size() const; int QJsonObject::length() const;
- 通過(guò) key 得到 value
QJsonValue QJsonObject::value(const QString &key) const; // utf8 QJsonValue QJsonObject::value(QLatin1String key) const; // 字符串不支持中文 QJsonValue QJsonObject::operator[](const QString &key) const; QJsonValue QJsonObject::operator[](QLatin1String key) const;
- 刪除鍵值對(duì)
void QJsonObject::remove(const QString &key); QJsonValue QJsonObject::take(const QString &key); // 返回key對(duì)應(yīng)的value值
- 通過(guò) key 進(jìn)行查找
iterator QJsonObject::find(const QString &key); bool QJsonObject::contains(const QString &key) const;
遍歷,方式有三種:
- 使用相關(guān)的迭代器函數(shù)
- 使用 [] 的方式遍歷,類似于遍歷數(shù)組,[] 中是鍵值
- 先得到對(duì)象中所有的鍵值,在遍歷鍵值列表,通過(guò) key 得到 value 值
QStringList QJsonObject::keys() const;
QJsonDocument
- 它封裝了一個(gè)完整的
JSON
文檔,并且可以從 UTF-8 編碼的基于文本的表示以及 Qt 自己的二進(jìn)制格式讀取和寫(xiě)入該文檔。 QJsonObject
和QJsonArray
這兩個(gè)對(duì)象中的數(shù)據(jù)是不能直接轉(zhuǎn)換為字符串類型的,如果要進(jìn)行數(shù)據(jù)傳輸或者數(shù)據(jù)的持久化,操作的都是字符串類型而不是QJsonObject
或者QJsonArray
類型,我們需要通過(guò)一個(gè)Json
文檔類進(jìn)行二者之間的轉(zhuǎn)換。
下面依次介紹一下這兩個(gè)轉(zhuǎn)換流程應(yīng)該如何操作:
1. QJsonObject 或者 QJsonArray ===> 字符串
- 創(chuàng)建 QJsonDocument 對(duì)象
QJsonDocument::QJsonDocument(const QJsonObject &object); QJsonDocument::QJsonDocument(const QJsonArray &array);
可以看出,通過(guò)構(gòu)造函數(shù)就可以將實(shí)例化之后的 QJsonObject 或者 QJsonArray 轉(zhuǎn)換為 QJsonDocument 對(duì)象了。
- 將文件對(duì)象中的數(shù)據(jù)進(jìn)行序列化
// 二進(jìn)制格式的json字符串 QByteArray QJsonDocument::toBinaryData() const; // 文本格式 QByteArray QJsonDocument::toJson(JsonFormat format = Indented) const;
通過(guò)調(diào)用 toxxx() 方法就可以得到文本格式或者二進(jìn)制格式的 Json 字符串了。
- 使用得到的字符串進(jìn)行數(shù)據(jù)傳輸,或者磁盤(pán)文件持久化
2. 字符串 ===> QJsonObject 或者 QJsonArray
一般情況下,通過(guò)網(wǎng)絡(luò)通信或者讀磁盤(pán)文件就會(huì)得到一個(gè) Json 格式的字符串,如果想要得到相關(guān)的原始數(shù)據(jù)就需要對(duì)字符串中的數(shù)據(jù)進(jìn)行解析,具體解析流程如下:
- 將得到的 Json 格式字符串通過(guò) QJsonDocument 類的靜態(tài)函數(shù)轉(zhuǎn)換為 QJsonDocument 類對(duì)象
[static] QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation = Validate); // 參數(shù)文件格式的json字符串 [static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR);
- 將文檔對(duì)象轉(zhuǎn)換為 json 數(shù)組 / 對(duì)象
// 判斷文檔對(duì)象中存儲(chǔ)的數(shù)據(jù)是不是數(shù)組 bool QJsonDocument::isArray() const; // 判斷文檔對(duì)象中存儲(chǔ)的數(shù)據(jù)是不是json對(duì)象 bool QJsonDocument::isObject() const // 文檔對(duì)象中的數(shù)據(jù)轉(zhuǎn)換為json對(duì)象 QJsonObject QJsonDocument::object() const; // 文檔對(duì)象中的數(shù)據(jù)轉(zhuǎn)換為json數(shù)組 QJsonArray QJsonDocument::array() const;
- 通過(guò)調(diào)用 QJsonArray , QJsonObject 類提供的 API 讀出存儲(chǔ)在對(duì)象中的數(shù)據(jù)。
關(guān)于 Qt 中 Json 數(shù)據(jù)對(duì)象以及字符串之間的轉(zhuǎn)換的操作流程是固定的,我們?cè)诰幋a過(guò)程中只需要按照上述模板處理即可,相關(guān)的操作是沒(méi)有太多的技術(shù)含量可言的。
實(shí)戰(zhàn)
1. 手動(dòng)寫(xiě)Json文件
注意:[…] 中是數(shù)組元素,{…}中是Json對(duì)象
2. 實(shí)現(xiàn)程序(從Json文件中讀取數(shù)據(jù),更改Json文件中的數(shù)據(jù))
mainwindow.h
class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); QVector<struct Animal> readJson();// 讀取Json文件 bool changeDate();// 改變Json文件中的數(shù)據(jù) private: Ui::MainWindow *ui; }; struct Food{ QString stapleFood; QString meat; }; struct Animal{ QString name; int age; QVector<QString> eatTimeArr; struct Food food; };
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); changeDate(); readJson(); } MainWindow::~MainWindow() { delete ui; } // 增加數(shù)據(jù)直接在手動(dòng)修改Json文件 // 查數(shù)據(jù)(已知Json數(shù)據(jù)格式的情況下):將Json中所有animal類保存到vector中全部返回 QVector<struct Animal> MainWindow::readJson() { QFile file("D:\\Qt\\homework\\text01\\studyJson.json"); bool ret = file.open(QFile::ReadOnly); QByteArray bytes = file.readAll();// 把文件中所有數(shù)據(jù)讀取出來(lái) QJsonDocument doc = QJsonDocument::fromJson(bytes);// 將讀出的數(shù)據(jù)保存為Json文檔 QJsonArray groupArr = doc.array();// 獲取數(shù)組 QVector<struct Animal> ans;// 用于保存獲取到的數(shù)據(jù) for(int i = 0; i < groupArr.size(); i++) { QJsonObject obj = groupArr.at(i).toObject();// 把數(shù)組中每一個(gè)數(shù)據(jù)都轉(zhuǎn)化為 QJsonObject struct Animal animal; animal.name = obj.value("name").toString(); animal.age = obj.value("age").toInt(); // eatTime 對(duì)應(yīng)的值為一個(gè)數(shù)組 QJsonArray foodArr = obj.value("eatTime").toArray(); for(int i = 0; i < foodArr.size(); i++) { animal.eatTimeArr.push_back(foodArr.at(i).toString()); } // food 對(duì)應(yīng)的值為一個(gè) QJsonObject 類型 QJsonObject subObj = obj.value("food").toObject(); animal.food.stapleFood = subObj.value("stapleFood").toString(); animal.food.meat = subObj.value("meat").toString(); ans.push_back(animal);// 將獲取到的數(shù)據(jù)加入容器中 qDebug() << "name =" << animal.name << "age =" << animal.age << "eatTime =" << animal.eatTimeArr[0] << animal.eatTimeArr[1] << animal.eatTimeArr[2] << "food.stapleFood =" << animal.food.stapleFood << "food.meat =" << animal.food.meat; } return ans; } // 改數(shù)據(jù):從studyJson.json讀取數(shù)據(jù)并且富貴的年齡改為10歲 bool MainWindow::changeDate() { // 打開(kāi)文件 QFile file("D:\\Qt\\homework\\text01\\studyJson.json"); file.open(QIODevice::ReadWrite); QByteArray bytes = file.readAll();// 讀取文件所有內(nèi)容 file.close(); QJsonDocument doc = QJsonDocument::fromJson(bytes);// 將讀出的數(shù)據(jù)保存為Json文檔 QJsonArray groupArr = doc.array();// 獲取數(shù)組 QJsonObject obj = groupArr.at(0).toObject();// 獲取數(shù)組中第一個(gè)元素 // 判斷 "age"節(jié)點(diǎn)是否存在 if(obj.contains("age")){ obj["age"] = 10;// 將數(shù)組第一個(gè)元素中的年齡改變 // 此時(shí)我們新建一個(gè)數(shù)組,把更新好的元素加入數(shù)組,并且把之前數(shù)組中沒(méi)有改變的元素加入 QJsonArray arr; arr.append(obj); arr.append(groupArr.at(1).toObject()); // 保存至Json文檔 注意:調(diào)用setArray后,先會(huì)把之前保存所有的數(shù)據(jù)清除,然后再保存新的數(shù)據(jù) doc.setArray(arr); } // 把最新數(shù)據(jù)寫(xiě)入QIODevice::Truncate file.open(QFile::WriteOnly|QFile::Truncate); file.seek(0);// 使寫(xiě)入位置為起始位置 file.write(doc.toJson()); }
打印調(diào)試信息
執(zhí)行changeDate()后,Json文件改變
這里需要注意:如果用Json自己寫(xiě)入文件,他所有數(shù)據(jù)會(huì)根據(jù)key的字典序排列
到此這篇關(guān)于Qt使用Json的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)Qt使用Json內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++中關(guān)于Crt的內(nèi)存泄漏檢測(cè)的分析介紹
本篇文章介紹了,在C++中關(guān)于Crt的內(nèi)存泄漏檢測(cè)的分析說(shuō)明。需要的朋友參考下2013-04-04Linux系統(tǒng)下C語(yǔ)言gets函數(shù)出現(xiàn)警告問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于在Linux系統(tǒng)下C語(yǔ)言gets函數(shù)出現(xiàn)警告問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)順序表的進(jìn)階講解
程序中經(jīng)常需要將一組數(shù)據(jù)元素作為整體管理和使用,需要?jiǎng)?chuàng)建這種元素組,用變量記錄它們,傳進(jìn)傳出函數(shù)等。一組數(shù)據(jù)中包含的元素個(gè)數(shù)可能發(fā)生變化,順序表則是將元素順序地存放在一塊連續(xù)的存儲(chǔ)區(qū)里,元素間的順序關(guān)系由它們的存儲(chǔ)順序自然表示2022-04-04二叉樹(shù)中葉子節(jié)點(diǎn)的統(tǒng)計(jì)和樹(shù)高問(wèn)題
今天小編就為大家分享一篇關(guān)于二叉樹(shù)中葉子節(jié)點(diǎn)的統(tǒng)計(jì)和樹(shù)高問(wèn)題,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03基于Qt開(kāi)發(fā)獲取CTP量化交易接口測(cè)試數(shù)據(jù)工具
這篇文章主要為大家詳細(xì)介紹了如何使用Qt軟件開(kāi)發(fā)K線股P相關(guān)軟件,先開(kāi)發(fā)一個(gè)通過(guò)CTP量化交易的sdk獲取相關(guān)推送數(shù)據(jù)的工具,需要的可以參考下2024-04-04C/C++格式化日志庫(kù)實(shí)現(xiàn)代碼
這篇文章主要介紹了C/C++格式化日志庫(kù)實(shí)現(xiàn)代碼,需要的朋友可以參考下2019-04-04