Qt服務應用操作之JSON文件操作方法
引言
在Qt框架中,JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,易于人閱讀和編寫,同時也易于機器解析和生成。Qt提供了多個類來支持JSON的解析、生成、修改和序列化,使得在Qt應用程序中處理JSON數(shù)據(jù)變得簡單高效。本文將詳細介紹如何在Qt中操作JSON文件。
一、JSON基礎知識
JSON主要有兩種數(shù)據(jù)結構:JSON對象和JSON數(shù)組。
JSON對象:由鍵值對組成,每個鍵(key)是字符串,值(value)可以是字符串、數(shù)字、布爾值、null、JSON數(shù)組或JSON對象。對象以花括號
{}包裹,鍵值對之間用逗號,分隔,鍵與值之間以冒號:分隔。// 示例一:JSON對象 { "name": "John Doe", "age": 30, "isEmployed": true }JSON數(shù)組:一系列有序的值的集合,其元素可以是任何JSON類型,包括其他數(shù)組或對象。數(shù)組以方括號
[]包裹,元素之間用逗號,分隔。// 示例二:JSON數(shù)組 ["Apple", "Banana", {"id": 1, "color": "Red"}]
二、Qt中處理JSON的關鍵類
Qt中處理JSON數(shù)據(jù)主要涉及以下幾個類:
- QJsonDocument:代表整個JSON文檔,負責從/向UTF-8文本或Qt內部二進制格式進行序列化與反序列化。
- QJsonObject:表示JSON對象,封裝了鍵值對的管理。
- QJsonArray:表示JSON數(shù)組,實現(xiàn)了動態(tài)大小的值列表。
- QJsonValue:封裝了JSON支持的數(shù)據(jù)類型,包括字符串、數(shù)字、布爾值、null、對象和數(shù)組。
- QJsonParseError:用于報告JSON解析中的錯誤類型。
// 相關頭文件 #include <QFile> // 文件操作 #include <QJsonObject> // JSON對象 #include <QJsonArray> // JSON數(shù)組 #include <QJsonDocument> // JSON文檔 #include <QJsonParseError> // JSON異常捕捉
三、生成JSON數(shù)據(jù)
在Qt中,可以通過組合使用上述類來創(chuàng)建復雜的JSON數(shù)據(jù)結構。以下是一個示例函數(shù),展示如何創(chuàng)建一個包含嵌套對象和數(shù)組的JSON對象:
// 生成復雜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;
}
// 運行結果在文章末尾四、解析JSON數(shù)據(jù)
給定一個JSON字符串,可以使用Qt的類將其解析為相應的對象或數(shù)組結構。以下是一個解析JSON字符串的示例:
// 解析JSON對象
QString parseAndPrintJSON(const QString &jsonString) {
QString strtemp; // 解析后的內容
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(); // 將它轉換為JSON對象
for (auto it = object.begin(); it != object.end(); ++it) {
const QString key = it.key();
strtemp += "\nKey: " + key;
qDebug() << "Key:" << key;
// 此處可根據(jù)自己需求進一步處理
}
}
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 << "文件進行寫入" ;
return;
}
/*
若使用QTextStream,需包含頭文件"QTextStream"
QTextStream out(&file);
out << doc.toJson(QJsonDocument::Indented);
*/
// 這里使用QFile
file.write(doc.toJson(QJsonDocument::Indented)); // 使用縮進格式使其更易于閱讀
file.close();
}在上面示例函數(shù)中,我們使用了QJsonDocument::Indented選項來生成格式化的JSON字符串,這使得文件內容更易于人類閱讀。然而,如果你關心文件大小或性能,可以選擇不使用縮進(即省略QJsonDocument::Indented參數(shù))。
六、從文件讀取JSON數(shù)據(jù)
從文件讀取JSON數(shù)據(jù)是上述保存過程的逆過程,使用QFile和QTextStream讀取文件內容,然后使用QJsonDocument::fromJson方法解析JSON字符串,。
// 讀取文件數(shù)據(jù)
QString loadJsonFromFile(const QString &fileName) {
QFile file(fileName);
// 若文件打開失敗,異常處理
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCritical() << "無法打開"<< fileName << "文件進行讀取";
return NULL;
}
/*
若使用QTextStream,需包含頭文件"QTextStream"
QTextStream in(&file);
QString jsonString = in.readAll();
*/
QString jsonString = file.readAll(); // 讀取全部內容
file.close(); // 關閉文件
return jsonString; // 返回讀取內容,注意:此處內容未解析,可以和上述的解析函數(shù)結合使用
} 七、代碼及運行結果
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. 生成復雜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; // 解析后的內容
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(); // 將它轉換為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ù)自己需求進一步處理
}*/
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 << "文件進行寫入" ;
return;
}
/*
若使用QTextStream
QTextStream out(&file);
out << doc.toJson(QJsonDocument::Indented);
*/
// 這里使用QFile
file.write(doc.toJson(QJsonDocument::Indented)); // 使用縮進格式使其更易于閱讀
file.close();
}
// 4. 讀取文件數(shù)據(jù)
QString loadJsonFromFile(const QString &fileName) {
QFile file(fileName);
// 若文件打開失敗,異常處理
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCritical() << "無法打開"<< fileName << "文件進行讀取";
return NULL;
}
/*
若使用QTextStream,需包含頭文件"QTextStream"
QTextStream in(&file);
QString jsonString = in.readAll();
*/
QString jsonString = file.readAll(); // 讀取全部內容
file.close(); // 關閉文件
return jsonString; // 返回讀取內容,注意:此處內容未解析,可以和上述的解析函數(shù)結合使用
}
// 將數(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. 運行結果
- 點擊:寫入JSON文件信息

查看person.json文件:

- 點擊:讀取JSON文件信息

八、總結
在Qt中處理JSON數(shù)據(jù)是一個常見且重要的任務,特別是在需要與Web服務、配置文件或其他基于JSON的數(shù)據(jù)源進行交互的應用程序中。通過本文的講解,我們了解了在Qt中處理JSON數(shù)據(jù)的幾個關鍵步驟,包括生成JSON數(shù)據(jù)、解析JSON字符串、遍歷JSON對象和數(shù)組、以及將JSON數(shù)據(jù)保存到文件和從文件讀取JSON數(shù)據(jù)。
生成JSON數(shù)據(jù):
我們使用QJsonObject和QJsonArray來構建JSON對象和數(shù)組。QJsonObject用于存儲鍵值對,而QJsonArray則用于存儲值的數(shù)組。通過將這些對象組合起來,我們可以構建復雜的JSON結構。解析JSON字符串:
使用QJsonDocument::fromJson()方法將JSON格式的字符串解析為QJsonDocument對象。如果解析成功,我們可以進一步將QJsonDocument對象轉換為QJsonObject或QJsonArray,以便訪問JSON數(shù)據(jù)。遍歷JSON對象和數(shù)組:
對于QJsonObject,我們可以使用value()方法來訪問其鍵值對。對于QJsonArray,我們可以使用迭代器或索引來遍歷其元素。每個元素可以是另一個QJsonObject、QJsonArray或基本數(shù)據(jù)類型的值。保存JSON數(shù)據(jù)到文件:
將QJsonDocument對象轉換為QByteArray,然后使用QFile和QTextStream(或QDataStream,但通常對于文本數(shù)據(jù),QTextStream更合適)將字節(jié)數(shù)組寫入文件。我們可以使用QJsonDocument::toJson()方法,并可選地指定縮進,以生成易于閱讀的JSON格式。從文件讀取JSON數(shù)據(jù):
使用QFile和QTextStream(或QDataStream)從文件讀取JSON字符串,然后使用QJsonDocument::fromJson()方法將其解析為QJsonDocument對象。錯誤處理:
在解析JSON字符串和打開文件時,我們始終應該檢查是否發(fā)生了錯誤,并適當?shù)靥幚硭鼈?。例如,如果JSON字符串格式不正確或文件無法打開,我們應該向用戶報告錯誤并可能采取恢復措施。
通過掌握這些基本技能,你可以在Qt應用程序中有效地使用JSON數(shù)據(jù),無論是用于配置管理、網(wǎng)絡通信還是數(shù)據(jù)持久化。JSON的靈活性、易用性和普及性使其成為許多現(xiàn)代應用程序中數(shù)據(jù)交換的首選格式。
到此這篇關于Qt服務應用操作之JSON文件操作方法的文章就介紹到這了,更多相關Qt JSON文件操作內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C語言結構體鏈表和指針實現(xiàn)學生管理系統(tǒng)
這篇文章主要介紹了C語言結構體鏈表和指針實現(xiàn)學生管理系統(tǒng),包括學生檔案管理子系統(tǒng)和學生成績管理子系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06
對比分析C語言中的gcvt()和ecvt()以及fcvt()函數(shù)
這篇文章主要介紹了對比分析C語言中的gcvt和ecvt以及fcvt函數(shù),都是將數(shù)字轉化為字符串,注意其之間的功能區(qū)別,需要的朋友可以參考下2015-08-08
C++編程使用findfirst和findnext查找及遍歷文件實現(xiàn)示例
這篇文章主要為大家介紹了C++編程如何使用findfirst和findnext查找及遍歷文件實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10

