QT中QJson详细解析+代码演示

QJson轻量级的数据交换格式

JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

Qt在5.0版本以后加入了对JSON的支持,因此直接包含相关的头文件即可操作Json数据的封装和解析。

QT中QJson详细解析+代码演示_第1张图片

需要包含的头文件:

#include 

#include 

#include 

#include 

#include 

JSON 常用类

QJsonDocument

QJsonDocument 类用于读和写 JSON 文档。

一个 JSON 文档可以使用 QJsonDocument::fromJson() 从基于文本的表示转化为 QJsonDocument, toJson() 则可以反向转化为文本。解析器非常快且高效,并将 JSON 转换为 Qt 使用的二进制表示。

已解析文档的有效性,可以使用 !isNull() 进行查询。

如果要查询一个 JSON 文档是否包含一个数组或一个对象,使用 isArray() 和 isObject()。包含在文档中的数组或对象可以使用 array() 或 object() 检索,然后读取或操作。

也可以使用 fromBinaryData() 或 fromRawData() 从存储的二进制表示创建来 JSON 文档。

QJsonArray

QJsonArray 类封装了一个 JSON 数组。

JSON 数组是值的列表。列表可以被操作,通过从数组中插入和删除 QJsonValue 。

一个 QJsonArray 可以和一个 QVariantList 相互转换。可以使用 size() 来查询条目的数量,通过 insert() 在指定索引处插入值,removeAt() 来删除指定索引的值。

QJsonObject

QJsonObject 类封装了一个 JSON 对象。

一个 JSON 对象是一个“key/value 对”列表,key 是独一无二的字符串,value 由一个 QJsonValue 表示。

一个 QJsonObject 可以和一个 QVariantMap 相互转换。可以使用 size() 来查询“key/value 对”的数量,通过 insert() 插入“key/value 对”, remove() 删除指定的 key。

QJsonValue

QJsonValue 类封装了一个值。

JSON 中的值有 6 种基本数据类型:

  • bool(QJsonValue::Bool)
  • double(QJsonValue::Double)
  • string(QJsonValue::String)
  • array(QJsonValue::Array)
  • object(QJsonValue::Object)
  • null(QJsonValue::Null)

一个值可以由任何上述数据类型表示。此外,QJsonValue 有一个特殊的标记来表示未定义的值,可以使用 isUndefined() 查询。

值的类型可以通过 type() 或 isBool()、isString() 等访问函数查询。同样地,值可以通过 toBool()、toString() 等函数转化成相应的存储类型。

QJsonParseError

QJsonParseError 类用于在 JSON 解析中报告错误。

枚举 QJsonParseError::ParseError:

该枚举描述 JSON 文档在解析过程中所发生的错误类型。

QT中QJson详细解析+代码演示_第2张图片

下面直接演示QJson的数据封包和解析。

QT中QJson详细解析+代码演示_第3张图片

QJson封包代码

QJsonObject sOne, sTwo, language, languages;
    sOne.insert("grade", 10);
    sOne.insert("language", "汉语");
    sTwo.insert("grade", 6);
    sTwo.insert("language", "英语");
    language.insert("serialone", sOne);
    language.insert("serialtwo", sTwo);
    languages.insert("languages", language);

    QJsonDocument json_document;
    json_document.setObject(languages);
    QByteArray byte_array = json_document.toJson(QJsonDocument::Compact);
    QString json_str(byte_array);
qDebug()<<json_str;

QT中QJson详细解析+代码演示_第4张图片

第10行实例化4个QJsonObject类对象,11-14行分别给sOne、sTwo插入数据,插入的方式与QMap插入键值对形式相同(Key是字符类型,T是不固定的类型),第15-16行是向language插入数据,这个时候的值是sOne、sTwo,第17行是向languages插入数据,这个时候的值是language,预期效果是这样的:

QT中QJson详细解析+代码演示_第5张图片

第19行实例化一个QJsonDocument对象,json_document调用setObject()函数将languages设置成QJson能够识别的键值队列,然后在第21行中使用toJson()函数将数据序列化为Json格式字符串,并赋值给一个QByteArray对象,第22行QString强转QByteArray将其变为QString格式,并在第23行使用QDebug进行打印输出。

运行效果:

在这里插入图片描述

实际运行效果与预期效果不同,预期效果是笔者为了阅读方便自行组织的,实际应用中以运行效果为准。运行效果中的反斜线‘\’是系统自己加入的为了转义并显示双引号“””。

QJson解析,解析的内容就以上面的封包为例,代码:

QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(json_str.toUtf8(), &jsonError);
if (jsonError.error != QJsonParseError::NoError && !doc.isNull()) {
qDebug() << "Json格式错误!" << jsonError.error;
return;

}//封包数据正确性判断

QJsonObject parse = doc.object();

QJsonValue value = parse.value("languages");

if(value.type() == QJsonValue::Object){

QJsonObject _parse = value.toObject();

QJsonValue _value = _parse.value("serialone");

if(_value.type() == QJsonValue::Object){

QJsonObject __parse = _value.toObject();

QJsonValue grade = __parse.value("grade");

int var = grade.toInt();

qDebug()<<"grade:"<<var;

QJsonValue language = __parse.value("language");

QString str = language.toString();

qDebug()<<"language:"<<str;

}

QJsonValue __value = _parse.value("serialtwo");

if(__value.type() == QJsonValue::Object){

QJsonObject __parse = __value.toObject();

QJsonValue grade = __parse.value("grade");

int var = grade.toInt();

qDebug()<<"grade:"<<var;

QJsonValue language = __parse.value("language");

QString str = language.toString();

qDebug()<<"language:"<<str;
}
}

QT中QJson详细解析+代码演示_第6张图片

第25行实例化一个QJsonParseError的对象,第26行实例化一个QJsonDocument对象预存将要解析的数据,fromJson()函数的作用是将原始的Json字符串转换为QJsonDocument可以识别的格式,参数json_str是上面我们封包的数据,同时引用了jsonError,第27~30行判断当前的Json数据是否有误,如果异常将返回失败,结束解析。

第32~54行进入解析流程,这里理解起来比较抽象,首先提到一个概念object,什么是object?封包中讲解的“languages”、“serialone”、“serialtwo”都叫做object,他们是项或者可以称为“容器”,同QMap容器相似,object的内容也是以类似“键-值”对的形式存在,以“serialone”为例,它的键是“grade”和“language”,对应的值分别是“10”、“汉语”,以“languages”为例,它的键是“serialone”和“serialtwo”,对应的值分别是各自的内容,但严格来讲,“languages”之于“serialone”和“serialtwo”已经不是标准的“键-值”对格式,而是一种上下级的嵌套关系,随着使用的熟练我们会知道,嵌套在Json中是常用的数据关联格式。

第32行实例化QJsonObject是为了获取第一级object也就是“languages”,第33行使用value()函数将“languages”转化为QJsonValue,QJsonValue存放的内容是一级object的嵌套内容,也就是“serialone”和“serialtwo”,然后在第35行再次实例化QJsonObject,将“serialone”和“serialtwo”这两级object取出,第37行和第46行分别取出“serialone”、“serialtwo”的内容,接下来就可以对第二级object进行解析了,注意,在封包阶段定义成什么格式的值,解析后就必须要用对应格式的变量进行存储,例如,“grade”对应的值是十进制数10,那么解析出来的值就要使用整型进行存储。

运行效果:

在这里插入图片描述

简单的 JSON 对象

构造一个简单的 JSON 对象:

{
    "Cross Platform": true,
    "From": 1991,
    "Name": "Qt"
}

生成比较简单,由于是一个对象,只需要用 QJsonObject 即可。

// 构建 JSON 对象
QJsonObject json;
json.insert("Name", "Qt");
json.insert("From", 1991);
json.insert("Cross Platform", true);

// 构建 JSON 文档
QJsonDocument document;
document.setObject(json);
QByteArray byteArray = document.toJson(QJsonDocument::Compact);
QString strJson(byteArray);

qDebug() << strJson;

解析如下:

QJsonParseError jsonError;
QJsonDocument doucment = QJsonDocument::fromJson(byteArray, &jsonError);  // 转化为 JSON 文档
if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {  // 解析未发生错误
    if (doucment.isObject()) { // JSON 文档为对象
        QJsonObject object = doucment.object();  // 转化为对象
        if (object.contains("Name")) {  // 包含指定的 key
            QJsonValue value = object.value("Name");  // 获取指定 key 对应的 value
            if (value.isString()) {  // 判断 value 是否为字符串
                QString strName = value.toString();  // 将 value 转化为字符串
                qDebug() << "Name : " << strName;
            }
        }
        if (object.contains("From")) {
            QJsonValue value = object.value("From");
            if (value.isDouble()) {
                int nFrom = value.toVariant().toInt();
                qDebug() << "From : " << nFrom;
            }
        }
        if (object.contains("Cross Platform")) {
            QJsonValue value = object.value("Cross Platform");
            if (value.isBool()) {
                bool bCrossPlatform = value.toBool();
                qDebug() << "CrossPlatform : " << bCrossPlatform;
            }
        }
    }
}

**注意:**在转化为 QJsonDocument 后,首先需要根据 QJsonParseError 的值判定是否转化成功,然后在进行相应的转化解析。

简单的 JSON 数组

构造一个简单的 JSON 对象:

[
    "Qt",
    5.7,
    true
]

生成比较简单,由于是一个数组,只需要用 QJsonArray 即可。

// 构建 JSON 数组
QJsonArray json;
json.append("Qt");
json.append(5.7);
json.append(true);

// 构建 JSON 文档
QJsonDocument document;
document.setArray(json);
QByteArray byteArray = document.toJson(QJsonDocument::Compact);
QString strJson(byteArray);

qDebug() << strJson;

需要注意的是,和上面不同的是,这里使用的是 QJsonDocument 的 setArray() 函数,因为是数组嘛!

解析如下:

QJsonParseError jsonError;
QJsonDocument doucment = QJsonDocument::fromJson(byteArray, &jsonError);  // 转化为 JSON 文档
if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误
    if (doucment.isArray()) { // JSON 文档为数组
        QJsonArray array = doucment.array();  // 转化为数组
        int nSize = array.size();  // 获取数组大小
        for (int i = 0; i < nSize; ++i) {  // 遍历数组
            QJsonValue value = array.at(i);
            if (value.type() == QJsonValue::String) {
                QString strName = value.toString();
                qDebug() << strName;
            }
            if (value.type() == QJsonValue::Double) {
                double dVersion = value.toDouble();
                qDebug() << dVersion;
            }
            if (value.type() == QJsonValue::Bool) {
                bool bCrossPlatform  = value.toBool();
                qDebug() << bCrossPlatform;
            }
        }
    }
}

和 JSON 对象类似,在遍历数组时,获取每个 value,首先需要判断 value 的类型(和 is***() 函数类似,这里根据 type() 函数返回的枚举值来判断),然后再进行相应的转换。

复杂的 JSON

构造一个复杂的 JSON 对象:

{
    "Company": "Digia",
    "From": 1991,
    "Name": "Qt",
    "Page": {
        "Developers": "https://www.qt.io/developers/",
        "Download": "https://www.qt.io/download/",
        "Home": "https://www.qt.io/"
    },
    "Version": [
        4.8,
        5.2,
        5.7
    ]
}

包含了一个拥有五个“key/value 对”的对象,values 中的两个(Company、Name)是字符串,一个(From)是数字,一个(Page)是对象,一个(Version)是数组。

要生成这样一个复杂的 JSON 文档,需要分别构造对象和数组,然后将它们拼接起来:

// 构建 Json 数组 - Version
QJsonArray versionArray;
versionArray.append(4.8);
versionArray.append(5.2);
versionArray.append(5.7);

// 构建 Json 对象 - Page
QJsonObject pageObject;
pageObject.insert("Home", "https://www.qt.io/");
pageObject.insert("Download", "https://www.qt.io/download/");
pageObject.insert("Developers", "https://www.qt.io/developers/");

// 构建 Json 对象
QJsonObject json;
json.insert("Name", "Qt");
json.insert("Company", "Digia");
json.insert("From", 1991);
json.insert("Version", QJsonValue(versionArray));
json.insert("Page", QJsonValue(pageObject));

// 构建 Json 文档
QJsonDocument document;
document.setObject(json);
QByteArray byteArray = document.toJson(QJsonDocument::Compact);
QString strJson(byteArray);

qDebug() << strJson;

解析部分其实并没有看起来这么复杂,只要一步步搞明白对应的类型,然后进行相应转化即可。

QJsonParseError jsonError;
QJsonDocument doucment = QJsonDocument::fromJson(byteArray, &jsonError);  // 转化为 JSON 文档
if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {  // 解析未发生错误
    if (doucment.isObject()) {  // JSON 文档为对象
        QJsonObject object = doucment.object();  // 转化为对象
        if (object.contains("Name")) {
            QJsonValue value = object.value("Name");
            if (value.isString()) {
                QString strName = value.toString();
                qDebug() << "Name : " << strName;
            }
        }
        if (object.contains("Company")) {
            QJsonValue value = object.value("Company");
            if (value.isString()) {
                QString strCompany = value.toString();
                qDebug() << "Company : " << strCompany;
            }
        }
        if (object.contains("From")) {
            QJsonValue value = object.value("From");
            if (value.isDouble()) {
                int nFrom = value.toVariant().toInt();
                qDebug() << "From : " << nFrom;
            }
        }
        if (object.contains("Version")) {
            QJsonValue value = object.value("Version");
            if (value.isArray()) {  // Version 的 value 是数组
                QJsonArray array = value.toArray();
                int nSize = array.size();
                for (int i = 0; i < nSize; ++i) {
                    QJsonValue value = array.at(i);
                    if (value.isDouble()) {
                        double dVersion = value.toDouble();
                        qDebug() << "Version : " << dVersion;
                    }
                }
            }
        }
        if (object.contains("Page")) {
            QJsonValue value = object.value("Page");
            if (value.isObject()) {  // Page 的 value 是对象
                QJsonObject obj = value.toObject();
                if (obj.contains("Home")) {
                    QJsonValue value = obj.value("Home");
                    if (value.isString()) {
                        QString strHome = value.toString();
                        qDebug() << "Home : " << strHome;
                    }
                }
                if (obj.contains("Download")) {
                    QJsonValue value = obj.value("Download");
                    if (value.isString()) {
                        QString strDownload = value.toString();
                        qDebug() << "Download : " << strDownload;
                    }
                }
                if (obj.contains("Developers")) {
                    QJsonValue value = obj.value("Developers");
                    if (value.isString()) {
                        QString strDevelopers = value.toString();
                        qDebug() << "Developers : " << strDevelopers;
                    }
                }
            }
        }
    }
}

基本的用法就这些,比较简单,细节很关键,建议在处理的过程中启用严格模式,例如:先通过 QJsonParseError::NoError 判断转化 JSON 文档无误,再进行解析。在解析过程中,先判断 QJsonValue 是否为对应的类型如 isObject(),再通过 toObject() 转化。
参考:https://www.cnblogs.com/lifan3a/articles/7811434.html

你可能感兴趣的:(QT,C++,qt,开发语言)