Qt服务应用操作之JSON文件操作方法

 更新时间:2024年10月30日 09:33:32   作者:J^T  
在Qt框架中,处理JSON数据包括解析、生成、保存和读取文件等操作,本文详细介绍了这些操作的关键类和方法,如QJsonDocument、QJsonObject、QJsonArray等,文中通过代码介绍的非常详细,需要的朋友可以参考下

引言

在Qt框架中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Qt提供了多个类来支持JSON的解析、生成、修改和序列化,使得在Qt应用程序中处理JSON数据变得简单高效。本文将详细介绍如何在Qt中操作JSON文件。

一、JSON基础知识

JSON主要有两种数据结构:JSON对象和JSON数组。

  • JSON对象:由键值对组成,每个键(key)是字符串,值(value)可以是字符串、数字、布尔值、null、JSON数组或JSON对象。对象以花括号{}包裹,键值对之间用逗号,分隔,键与值之间以冒号:分隔。

    // 示例一:JSON对象
    {
        "name": "John Doe",
         "age": 30,
         "isEmployed": true
    }
  • JSON数组:一系列有序的值的集合,其元素可以是任何JSON类型,包括其他数组或对象。数组以方括号[]包裹,元素之间用逗号,分隔。

    // 示例二:JSON数组
    ["Apple", "Banana", {"id": 1, "color": "Red"}]

二、Qt中处理JSON的关键类

Qt中处理JSON数据主要涉及以下几个类:

  • QJsonDocument:代表整个JSON文档,负责从/向UTF-8文本或Qt内部二进制格式进行序列化与反序列化。
  • QJsonObject:表示JSON对象,封装了键值对的管理。
  • QJsonArray:表示JSON数组,实现了动态大小的值列表。
  • QJsonValue:封装了JSON支持的数据类型,包括字符串、数字、布尔值、null、对象和数组。
  • QJsonParseError:用于报告JSON解析中的错误类型。
// 相关头文件
#include <QFile>    // 文件操作
#include <QJsonObject>  // JSON对象
#include <QJsonArray>   // JSON数组
#include <QJsonDocument>    // JSON文档
#include <QJsonParseError>  // JSON异常捕捉

三、生成JSON数据

在Qt中,可以通过组合使用上述类来创建复杂的JSON数据结构。以下是一个示例函数,展示如何创建一个包含嵌套对象和数组的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数组
    hobbiesArray.append("Reading");
    hobbiesArray.append("Gaming");
    personObject["hobbies"] = hobbiesArray;  // 嵌套JSON数组

    return personObject;
}
// 运行结果在文章末尾

四、解析JSON数据

给定一个JSON字符串,可以使用Qt的类将其解析为相应的对象或数组结构。以下是一个解析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;
            // 此处可根据自己需求进一步处理
        }
    }
    return strtemp;
}

五、保存JSON数据到文件

要将JSON数据保存到文件中,你可以使用QFileQTextStream(或QDataStream,但通常对于文本数据,QTextStream更合适)。首先,你需要将QJsonDocument对象序列化为QByteArray,然后将其写入文件。

// 保存JSON数据到文件
void saveJsonToFile(const QString &fileName, const QJsonObject &person) {
    // 创建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();
}

在上面示例函数中,我们使用了QJsonDocument::Indented选项来生成格式化的JSON字符串,这使得文件内容更易于人类阅读。然而,如果你关心文件大小或性能,可以选择不使用缩进(即省略QJsonDocument::Indented参数)。

六、从文件读取JSON数据

从文件读取JSON数据是上述保存过程的逆过程,使用QFileQTextStream读取文件内容,然后使用QJsonDocument::fromJson方法解析JSON字符串,。

// 读取文件数据
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; // 返回读取内容,注意:此处内容未解析,可以和上述的解析函数结合使用
} 

七、代码及运行结果

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(); // 将数据信息写入JSON文件槽函数

    void on_rJsonBtn_clicked();// 读取JSON文件数据槽函数

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数组
#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数组
    hobbiesArray.append("Reading");
    hobbiesArray.append("Gaming");
    personObject["hobbies"] = hobbiesArray;  // 嵌套JSON数组

    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;
            // 此处可根据自己需求进一步处理
        }*/
        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数据到文件
void saveJsonToFile(const QString &fileName, const QJsonObject &person) {
    // 创建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. 读取文件数据
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; // 返回读取内容,注意:此处内容未解析,可以和上述的解析函数结合使用
}


// 将数据信息写入JSON文件槽函数
void QJsonOper::on_wJsonBtn_clicked()
{
    // 生成JSON对象
    QJsonObject person = createJSONObject();

    // 保存JSON数据到文件
    saveJsonToFile("person.json", person);

    // 若保存成功,对话框弹出
    QMessageBox::information(this,"success", "恭喜你!成功保存JSON数据到文件!");
}

// 读取JSON文件数据槽函数
void QJsonOper::on_rJsonBtn_clicked()
{
    QString fileName = "person.json";
    // 读取JSON文件数据,注意未解析
    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数据是一个常见且重要的任务,特别是在需要与Web服务、配置文件或其他基于JSON的数据源进行交互的应用程序中。通过本文的讲解,我们了解了在Qt中处理JSON数据的几个关键步骤,包括生成JSON数据、解析JSON字符串、遍历JSON对象和数组、以及将JSON数据保存到文件和从文件读取JSON数据。

  • 生成JSON数据
    我们使用QJsonObjectQJsonArray来构建JSON对象和数组。QJsonObject用于存储键值对,而QJsonArray则用于存储值的数组。通过将这些对象组合起来,我们可以构建复杂的JSON结构。

  • 解析JSON字符串
    使用QJsonDocument::fromJson()方法将JSON格式的字符串解析为QJsonDocument对象。如果解析成功,我们可以进一步将QJsonDocument对象转换为QJsonObjectQJsonArray,以便访问JSON数据。

  • 遍历JSON对象和数组
    对于QJsonObject,我们可以使用value()方法来访问其键值对。对于QJsonArray,我们可以使用迭代器或索引来遍历其元素。每个元素可以是另一个QJsonObjectQJsonArray或基本数据类型的值。

  • 保存JSON数据到文件
    QJsonDocument对象转换为QByteArray,然后使用QFileQTextStream(或QDataStream,但通常对于文本数据,QTextStream更合适)将字节数组写入文件。我们可以使用QJsonDocument::toJson()方法,并可选地指定缩进,以生成易于阅读的JSON格式。

  • 从文件读取JSON数据
    使用QFileQTextStream(或QDataStream)从文件读取JSON字符串,然后使用QJsonDocument::fromJson()方法将其解析为QJsonDocument对象。

  • 错误处理
    在解析JSON字符串和打开文件时,我们始终应该检查是否发生了错误,并适当地处理它们。例如,如果JSON字符串格式不正确或文件无法打开,我们应该向用户报告错误并可能采取恢复措施。

通过掌握这些基本技能,你可以在Qt应用程序中有效地使用JSON数据,无论是用于配置管理、网络通信还是数据持久化。JSON的灵活性、易用性和普及性使其成为许多现代应用程序中数据交换的首选格式。

到此这篇关于Qt服务应用操作之JSON文件操作方法的文章就介绍到这了,更多相关Qt JSON文件操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 最新C语言中getchar的使用

    最新C语言中getchar的使用

    getchar()是在输入缓冲区顺序读入一个字符(包括空格、回车和Tab) ,getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,本文给大家介绍getchar的使用,感兴趣的朋友跟随小编一起看看吧
    2022-12-12
  • 浅谈c语言中一种典型的排列组合算法

    浅谈c语言中一种典型的排列组合算法

    下面小编就为大家带来一篇浅谈c语言中一种典型的排列组合算法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • VisualStudio中OpenCV的创建与配置使用小结

    VisualStudio中OpenCV的创建与配置使用小结

    本文介绍了OpenCV在Visual Studio中的配置步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • C++ 浅谈emplace_back及使用误区

    C++ 浅谈emplace_back及使用误区

    这篇文章主要介绍了C++ 浅谈emplace_back及使用误区,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • C++中关于多态实现和使用方法

    C++中关于多态实现和使用方法

    这篇文章主要介绍了C++中关于多态实现和使用方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C语言超全面覆盖操作符知识点

    C语言超全面覆盖操作符知识点

    C 语言提供了丰富的操作符,有:算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符等。让我们通读本篇来详细了解吧
    2022-06-06
  • C++ 情怀游戏贪吃蛇的实现流程详解

    C++ 情怀游戏贪吃蛇的实现流程详解

    贪吃蛇是曾经诺基亚手机上很经典很经典的传统老游戏,80.90后的童年时不多的游戏之一,跟电脑上的扫雷一样,下面来从贪吃蛇手机游戏的前世今生讲起
    2021-11-11
  • C语言中的数据类型强制转换

    C语言中的数据类型强制转换

    这篇文章主要介绍了C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • C++右移运算符的一个小坑及解决

    C++右移运算符的一个小坑及解决

    文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数
    2025-09-09
  • C语言基础知识变量的作用域和存储方式详细介绍

    C语言基础知识变量的作用域和存储方式详细介绍

    这篇文章主要介绍了C语言基础知识变量的作用域和存储方式详细介绍的相关资料,需要的朋友可以参考下
    2017-01-01

最新评论