Qt JSON 文件生成與解析

最近需要在Qt中解析修改保存JSON格式的文件來完成相關工作,網友分享的這篇文章很實用,特此記錄下來,方便自己下次查找,同時也分享給有需要的網友。

簡述

Qt5 中包含了處理 JSON 的類,均以 QJson 開頭(例如:QJsonDocument、QJsonArray、QJsonObject),在 QtCore 模塊中,不需要額外引入其它模塊。

常用的 JSON 庫

json.org 中介紹了 JSON 在各種語言中的應用,在 C/C++ 中比較常用的JSON 庫主要有以下幾個:

  • JsonCpp 
    JsonCpp 是一個 C++ 用來處理 JSON 數據的開發包。 
    網址:http://jsoncpp.sourceforge.net/

  • cJSON 
    cJSON 是一個超輕巧,攜帶方便,單文件,簡單的可以作爲 ANSI-C 標準的 JSON 解析器。 
    網址:http://sourceforge.net/projects/cjson/

  • QJson 
    QJson 是一個基於 Qt 的開發包用來將 JSON 數據解析成 QVariant 對象,JSON 的數組將被映射爲QVariantList 實例,而其他對象映射爲 QVariantMap 實例。 
    網址:http://qjson.sourceforge.net/

關於 Qt 中對 JSON 的生成與解析,Qt5 以前的版本,可以使用 QJson 庫,需要單獨下載、編譯,才能使用。到了 Qt5,提供了專門的 QJsonDocument 及其相關類來讀和寫 JSON 文檔。

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 文檔在解析過程中所發生的錯誤類型。

常量 描述
QJsonParseError::NoError 0 未發生錯誤
QJsonParseError::UnterminatedObject 1 對象不正確地終止以右花括號結束
QJsonParseError::MissingNameSeparator 2 分隔不同項的逗號丟失
QJsonParseError::UnterminatedArray 3 數組不正確地終止以右中括號結束
QJsonParseError::MissingValueSeparator 4 對象中分割 key/value 的冒號丟失
QJsonParseError::IllegalValue 5 值是非法的
QJsonParseError::TerminationByNumber 6 在解析數字時,輸入流結束
QJsonParseError::IllegalNumber 7 數字格式不正確
QJsonParseError::IllegalEscapeSequence 8 在輸入時,發生一個非法轉義序列
QJsonParseError::IllegalUTF8String 9 在輸入時,發生一個非法 UTF8 序列
QJsonParseError::UnterminatedString 10 字符串不是以引號結束
QJsonParseError::MissingObject 11 一個對象是預期的,但是不能被發現
QJsonParseError::DeepNesting 12 對解析器來說,JSON 文檔嵌套太深
QJsonParseError::DocumentTooLarge 13 對解析器來說,JSON 文檔太大
QJsonParseError::GarbageAtEnd 14 解析的文檔在末尾處包含額外的亂碼

簡單的 JSON 對象

構造一個簡單的 JSON 對象:

{
    "Cross Platform": true,
    "From": 1991,
    "Name": "Qt"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

生成比較簡單,由於是一個對象,只需要用 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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

解析如下:

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;
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

注意:在轉化爲 QJsonDocument 後,首先需要根據 QJsonParseError 的值判定是否轉化成功,然後在進行相應的轉化解析。

簡單的 JSON 數組

構造一個簡單的 JSON 對象:

[
    "Qt",
    5.7,
    true
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

生成比較簡單,由於是一個數組,只需要用 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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

需要注意的是,和上面不同的是,這裏使用的是 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;
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

和 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
    ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

包含了一個擁有五個“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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

解析部分其實並沒有看起來這麼複雜,只要一步步搞明白對應的類型,然後進行相應轉化即可。

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;
                    }
                }
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

基本的用法就這些,比較簡單,細節很關鍵,建議在處理的過程中啓用嚴格模式,例如:先通過 QJsonParseError::NoError 判斷轉化 JSON 文檔無誤,再進行解析。在解析過程中,先判斷 QJsonValue 是否爲對應的類型如 isObject(),再通過 toObject() 轉化。

更多參考


本文原文地址:http://blog.csdn.net/liang19890820/article/details/52767153#常用的-json-庫 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章