Qt服務(wù)應(yīng)用操作之JSON文件操作方法
引言
在Qt框架中,JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,易于人閱讀和編寫,同時也易于機(jī)器解析和生成。Qt提供了多個類來支持JSON的解析、生成、修改和序列化,使得在Qt應(yīng)用程序中處理JSON數(shù)據(jù)變得簡單高效。本文將詳細(xì)介紹如何在Qt中操作JSON文件。
一、JSON基礎(chǔ)知識
JSON主要有兩種數(shù)據(jù)結(jié)構(gòu):JSON對象和JSON數(shù)組。
JSON對象:由鍵值對組成,每個鍵(key)是字符串,值(value)可以是字符串、數(shù)字、布爾值、null、JSON數(shù)組或JSON對象。對象以花括號
{}
包裹,鍵值對之間用逗號,
分隔,鍵與值之間以冒號:
分隔。// 示例一:JSON對象 { "name": "John Doe", "age": 30, "isEmployed": true }
JSON數(shù)組:一系列有序的值的集合,其元素可以是任何JSON類型,包括其他數(shù)組或?qū)ο?。?shù)組以方括號
[]
包裹,元素之間用逗號,
分隔。// 示例二:JSON數(shù)組 ["Apple", "Banana", {"id": 1, "color": "Red"}]
二、Qt中處理JSON的關(guān)鍵類
Qt中處理JSON數(shù)據(jù)主要涉及以下幾個類:
- QJsonDocument:代表整個JSON文檔,負(fù)責(zé)從/向UTF-8文本或Qt內(nèi)部二進(jìn)制格式進(jìn)行序列化與反序列化。
- QJsonObject:表示JSON對象,封裝了鍵值對的管理。
- QJsonArray:表示JSON數(shù)組,實(shí)現(xiàn)了動態(tài)大小的值列表。
- QJsonValue:封裝了JSON支持的數(shù)據(jù)類型,包括字符串、數(shù)字、布爾值、null、對象和數(shù)組。
- QJsonParseError:用于報告JSON解析中的錯誤類型。
// 相關(guān)頭文件 #include <QFile> // 文件操作 #include <QJsonObject> // JSON對象 #include <QJsonArray> // JSON數(shù)組 #include <QJsonDocument> // JSON文檔 #include <QJsonParseError> // JSON異常捕捉
三、生成JSON數(shù)據(jù)
在Qt中,可以通過組合使用上述類來創(chuàng)建復(fù)雜的JSON數(shù)據(jù)結(jié)構(gòu)。以下是一個示例函數(shù),展示如何創(chuàng)建一個包含嵌套對象和數(shù)組的JSON對象:
// 生成復(fù)雜JSON對象 QJsonObject createJSONObject() { QJsonObject personObject; // JSON對象 // 方式一:insert()方法 personObject.insert("name","John Doe"); personObject.insert("age", 30); personObject.insert("isEmployed", true); QJsonObject addressObject; // 方式二:賦值 addressObject["street"] = "123 Main St."; addressObject["city"] = "Anytown"; addressObject["country"] = "USA"; personObject["address"] = addressObject; // 嵌套JSON對象 QJsonArray hobbiesArray; // JSON數(shù)組 hobbiesArray.append("Reading"); hobbiesArray.append("Gaming"); personObject["hobbies"] = hobbiesArray; // 嵌套JSON數(shù)組 return personObject; } // 運(yùn)行結(jié)果在文章末尾
四、解析JSON數(shù)據(jù)
給定一個JSON字符串,可以使用Qt的類將其解析為相應(yīng)的對象或數(shù)組結(jié)構(gòu)。以下是一個解析JSON字符串的示例:
// 解析JSON對象 QString parseAndPrintJSON(const QString &jsonString) { QString strtemp; // 解析后的內(nèi)容 QJsonParseError error; // 返回JSON解析錯誤的時候,報告錯誤信息 QJsonDocument document = QJsonDocument::fromJson(jsonString.toUtf8(), &error); if (error.error != QJsonParseError::NoError) { qCritical() << "JSON parsing error: " << error.errorString(); return NULL; } // 檢查保存的值是否是對象 if (document.isObject()) { QJsonObject object = document.object(); // 將它轉(zhuǎn)換為JSON對象 for (auto it = object.begin(); it != object.end(); ++it) { const QString key = it.key(); strtemp += "\nKey: " + key; qDebug() << "Key:" << key; // 此處可根據(jù)自己需求進(jìn)一步處理 } } return strtemp; }
五、保存JSON數(shù)據(jù)到文件
要將JSON數(shù)據(jù)保存到文件中,你可以使用QFile
和QTextStream
(或QDataStream
,但通常對于文本數(shù)據(jù),QTextStream
更合適)。首先,你需要將QJsonDocument
對象序列化為QByteArray
,然后將其寫入文件。
// 保存JSON數(shù)據(jù)到文件 void saveJsonToFile(const QString &fileName, const QJsonObject &person) { // 創(chuàng)建JSON文檔 QJsonDocument doc(person); QFile file(fileName); // 若文件打開失敗,異常處理 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qCritical() << "無法打開"<< fileName << "文件進(jìn)行寫入" ; return; } /* 若使用QTextStream,需包含頭文件"QTextStream" QTextStream out(&file); out << doc.toJson(QJsonDocument::Indented); */ // 這里使用QFile file.write(doc.toJson(QJsonDocument::Indented)); // 使用縮進(jìn)格式使其更易于閱讀 file.close(); }
在上面示例函數(shù)中,我們使用了QJsonDocument::Indented
選項(xiàng)來生成格式化的JSON字符串,這使得文件內(nèi)容更易于人類閱讀。然而,如果你關(guān)心文件大小或性能,可以選擇不使用縮進(jìn)(即省略QJsonDocument::Indented
參數(shù))。
六、從文件讀取JSON數(shù)據(jù)
從文件讀取JSON數(shù)據(jù)是上述保存過程的逆過程,使用QFile
和QTextStream
讀取文件內(nèi)容,然后使用QJsonDocument::fromJson
方法解析JSON字符串,。
// 讀取文件數(shù)據(jù) QString loadJsonFromFile(const QString &fileName) { QFile file(fileName); // 若文件打開失敗,異常處理 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qCritical() << "無法打開"<< fileName << "文件進(jìn)行讀取"; return NULL; } /* 若使用QTextStream,需包含頭文件"QTextStream" QTextStream in(&file); QString jsonString = in.readAll(); */ QString jsonString = file.readAll(); // 讀取全部內(nèi)容 file.close(); // 關(guān)閉文件 return jsonString; // 返回讀取內(nèi)容,注意:此處內(nèi)容未解析,可以和上述的解析函數(shù)結(jié)合使用 }
七、代碼及運(yùn)行結(jié)果
1. UI測試界面
2. 代碼示例
- qjsonoper.h
#ifndef QJSONOPER_H #define QJSONOPER_H #include <QDialog> QT_BEGIN_NAMESPACE namespace Ui { class QJsonOper; } QT_END_NAMESPACE class QJsonOper : public QDialog { Q_OBJECT public: QJsonOper(QWidget *parent = nullptr); ~QJsonOper(); private slots: void on_wJsonBtn_clicked(); // 將數(shù)據(jù)信息寫入JSON文件槽函數(shù) void on_rJsonBtn_clicked();// 讀取JSON文件數(shù)據(jù)槽函數(shù) private: Ui::QJsonOper *ui; }; #endif // QJSONOPER_H
- qjsonoper.cpp
#include "qjsonoper.h" #include "ui_qjsonoper.h" #include <QMessageBox> #include <QDebug> #include <QFile> // 文件操作 #include <QJsonObject> // JSON對象 #include <QJsonArray> // JSON數(shù)組 #include <QJsonDocument> // JSON文檔 #include <QJsonParseError> // JSON異常捕捉 QJsonOper::QJsonOper(QWidget *parent) : QDialog(parent) , ui(new Ui::QJsonOper) { ui->setupUi(this); } QJsonOper::~QJsonOper() { delete ui; } // 1. 生成復(fù)雜JSON對象 QJsonObject createJSONObject() { QJsonObject personObject; // JSON對象 // 方式一:insert()方法 personObject.insert("name","John Doe"); personObject.insert("age", 30); personObject.insert("isEmployed", true); QJsonObject addressObject; // 方式二:賦值 addressObject["street"] = "123 Main St."; addressObject["city"] = "Anytown"; addressObject["country"] = "USA"; personObject["address"] = addressObject; // 嵌套JSON對象 QJsonArray hobbiesArray; // JSON數(shù)組 hobbiesArray.append("Reading"); hobbiesArray.append("Gaming"); personObject["hobbies"] = hobbiesArray; // 嵌套JSON數(shù)組 return personObject; } // 2. 解析JSON對象 QString parseAndPrintJSON(const QString &jsonString) { QString strtemp; // 解析后的內(nèi)容 QJsonParseError error; // 返回JSON解析錯誤的時候,報告錯誤信息 QJsonDocument document = QJsonDocument::fromJson(jsonString.toUtf8(), &error); if (error.error != QJsonParseError::NoError) { qCritical() << "JSON parsing error: " << error.errorString(); return NULL; } // 檢查保存的值是否是對象 if (document.isObject()) { QJsonObject object = document.object(); // 將它轉(zhuǎn)換為JSON對象 QStringList keys = object.keys(); //得到所有key /*for (auto it = object.begin(); it != object.end(); ++it) { const QString key = it.key(); strtemp += "\nKey: " + key; qDebug() << "Key:" << key; // 此處可根據(jù)自己需求進(jìn)一步處理 }*/ for (int i = 0; i < keys.size(); i++) // 遍歷每一個鍵值 { QString key = keys.at(i); QJsonValue value = object.value(key); if (value.isBool()) { strtemp += key + ":" + value.toBool() + "\n"; } else if (value.isString()) { strtemp += key + ":" + value.toString() + "\n"; } else if (value.isDouble()) { strtemp += key + ":" + value.toDouble() + "\n"; } else if (value.isArray()) { strtemp += keys.at(i) + ":" + "\n"; QJsonArray array = value.toArray(); for (int j = 0; j < array.size(); j++) { strtemp += " " + array[j].toString() + "\n"; } } else if (value.isObject()) { strtemp += key + ":" + "\n"; QJsonObject subObj = value.toObject(); QStringList subKeys = subObj.keys(); for(int k = 0; k < subKeys.size(); ++k) { QJsonValue subValue = subObj.value(subKeys.at(k)); if (subValue.isString()) { strtemp += " " + subKeys.at(k) + ":" + subValue.toString() + "\n"; } else if (subValue.isArray()) { strtemp += subKeys.at(k) + ":" + "\n"; QJsonArray array = subValue.toArray(); for (int m = 0; m < array.size(); m++) { strtemp += " " + array[m].toString() + "\n"; } } } } } } return strtemp; } // 3. 保存JSON數(shù)據(jù)到文件 void saveJsonToFile(const QString &fileName, const QJsonObject &person) { // 創(chuàng)建JSON文檔 QJsonDocument doc(person); QFile file(fileName); // 若文件打開失敗,異常處理 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qCritical() << "無法打開"<< fileName << "文件進(jìn)行寫入" ; return; } /* 若使用QTextStream QTextStream out(&file); out << doc.toJson(QJsonDocument::Indented); */ // 這里使用QFile file.write(doc.toJson(QJsonDocument::Indented)); // 使用縮進(jìn)格式使其更易于閱讀 file.close(); } // 4. 讀取文件數(shù)據(jù) QString loadJsonFromFile(const QString &fileName) { QFile file(fileName); // 若文件打開失敗,異常處理 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qCritical() << "無法打開"<< fileName << "文件進(jìn)行讀取"; return NULL; } /* 若使用QTextStream,需包含頭文件"QTextStream" QTextStream in(&file); QString jsonString = in.readAll(); */ QString jsonString = file.readAll(); // 讀取全部內(nèi)容 file.close(); // 關(guān)閉文件 return jsonString; // 返回讀取內(nèi)容,注意:此處內(nèi)容未解析,可以和上述的解析函數(shù)結(jié)合使用 } // 將數(shù)據(jù)信息寫入JSON文件槽函數(shù) void QJsonOper::on_wJsonBtn_clicked() { // 生成JSON對象 QJsonObject person = createJSONObject(); // 保存JSON數(shù)據(jù)到文件 saveJsonToFile("person.json", person); // 若保存成功,對話框彈出 QMessageBox::information(this,"success", "恭喜你!成功保存JSON數(shù)據(jù)到文件!"); } // 讀取JSON文件數(shù)據(jù)槽函數(shù) void QJsonOper::on_rJsonBtn_clicked() { QString fileName = "person.json"; // 讀取JSON文件數(shù)據(jù),注意未解析 QString jsonString = loadJsonFromFile(fileName); // 解析JSON對象 QString str = parseAndPrintJSON(jsonString); // 若讀取成功,對話框彈出 QMessageBox::information(this,fileName, str, QMessageBox::Yes); }
- main.cpp
#include "qjsonoper.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); QJsonOper w; w.show(); return a.exec(); }
3. 運(yùn)行結(jié)果
- 點(diǎn)擊:寫入JSON文件信息
查看person.json文件:
- 點(diǎn)擊:讀取JSON文件信息
八、總結(jié)
在Qt中處理JSON數(shù)據(jù)是一個常見且重要的任務(wù),特別是在需要與Web服務(wù)、配置文件或其他基于JSON的數(shù)據(jù)源進(jìn)行交互的應(yīng)用程序中。通過本文的講解,我們了解了在Qt中處理JSON數(shù)據(jù)的幾個關(guān)鍵步驟,包括生成JSON數(shù)據(jù)、解析JSON字符串、遍歷JSON對象和數(shù)組、以及將JSON數(shù)據(jù)保存到文件和從文件讀取JSON數(shù)據(jù)。
生成JSON數(shù)據(jù):
我們使用QJsonObject
和QJsonArray
來構(gòu)建JSON對象和數(shù)組。QJsonObject
用于存儲鍵值對,而QJsonArray
則用于存儲值的數(shù)組。通過將這些對象組合起來,我們可以構(gòu)建復(fù)雜的JSON結(jié)構(gòu)。解析JSON字符串:
使用QJsonDocument::fromJson()
方法將JSON格式的字符串解析為QJsonDocument
對象。如果解析成功,我們可以進(jìn)一步將QJsonDocument
對象轉(zhuǎn)換為QJsonObject
或QJsonArray
,以便訪問JSON數(shù)據(jù)。遍歷JSON對象和數(shù)組:
對于QJsonObject
,我們可以使用value()
方法來訪問其鍵值對。對于QJsonArray
,我們可以使用迭代器或索引來遍歷其元素。每個元素可以是另一個QJsonObject
、QJsonArray
或基本數(shù)據(jù)類型的值。保存JSON數(shù)據(jù)到文件:
將QJsonDocument
對象轉(zhuǎn)換為QByteArray
,然后使用QFile
和QTextStream
(或QDataStream
,但通常對于文本數(shù)據(jù),QTextStream
更合適)將字節(jié)數(shù)組寫入文件。我們可以使用QJsonDocument::toJson()
方法,并可選地指定縮進(jìn),以生成易于閱讀的JSON格式。從文件讀取JSON數(shù)據(jù):
使用QFile
和QTextStream
(或QDataStream
)從文件讀取JSON字符串,然后使用QJsonDocument::fromJson()
方法將其解析為QJsonDocument
對象。錯誤處理:
在解析JSON字符串和打開文件時,我們始終應(yīng)該檢查是否發(fā)生了錯誤,并適當(dāng)?shù)靥幚硭鼈?。例如,如果JSON字符串格式不正確或文件無法打開,我們應(yīng)該向用戶報告錯誤并可能采取恢復(fù)措施。
通過掌握這些基本技能,你可以在Qt應(yīng)用程序中有效地使用JSON數(shù)據(jù),無論是用于配置管理、網(wǎng)絡(luò)通信還是數(shù)據(jù)持久化。JSON的靈活性、易用性和普及性使其成為許多現(xiàn)代應(yīng)用程序中數(shù)據(jù)交換的首選格式。
到此這篇關(guān)于Qt服務(wù)應(yīng)用操作之JSON文件操作方法的文章就介紹到這了,更多相關(guān)Qt JSON文件操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言結(jié)構(gòu)體鏈表和指針實(shí)現(xiàn)學(xué)生管理系統(tǒng)
這篇文章主要介紹了C語言結(jié)構(gòu)體鏈表和指針實(shí)現(xiàn)學(xué)生管理系統(tǒng),包括學(xué)生檔案管理子系統(tǒng)和學(xué)生成績管理子系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06對比分析C語言中的gcvt()和ecvt()以及fcvt()函數(shù)
這篇文章主要介紹了對比分析C語言中的gcvt和ecvt以及fcvt函數(shù),都是將數(shù)字轉(zhuǎn)化為字符串,注意其之間的功能區(qū)別,需要的朋友可以參考下2015-08-08C語言中字符串的內(nèi)存地址操作的相關(guān)函數(shù)簡介
這篇文章主要介紹了C語言中字符串的內(nèi)存地址操作的相關(guān)函數(shù),包括bcopy()函數(shù)和bzero()函數(shù)以及bcmp()函數(shù),需要的朋友可以參考下2015-08-08C++編程使用findfirst和findnext查找及遍歷文件實(shí)現(xiàn)示例
這篇文章主要為大家介紹了C++編程如何使用findfirst和findnext查找及遍歷文件實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10