#(64):使用 QJsonDocument 處理 JSON
上一章我們了解了如何使用 QJson 處理 JSON 文檔。QJson 是一個基于 Qt 的第三方庫,適用于 Qt4 和 Qt5 兩個版本。不過,如果你的應用僅僅需要考慮兼容 Qt5,其實已經有了內置的處理函數。Qt5 新增加了處理 JSON 的類,與 XML 類庫類似,均以 QJson 開頭,在 QtCore 模塊中,不需要額外引入其它模塊。Qt5 新增加六個相關類:
| `QJsonArray` | 封裝 JSON 數組 |
| -- || -- |
| `QJsonDocument` | 讀寫 JSON 文檔 |
| `QJsonObject` | 封裝 JSON 對象 |
| `QJsonObject::iterator` | 用于遍歷`QJsonObject`的 STL 風格的非 const 遍歷器 |
| `QJsonParseError` | 報告 JSON 處理過程中出現的錯誤 |
| `QJsonValue` | 封裝 JSON 值 |
我們還是使用前一章的 JSON?文檔,這次換用`QJsonDocument`?來解析。注意,`QJsonDocument`要求使用 Qt5,本章中所有代碼都必須在 Qt5?環境下進行編譯運行。
~~~
QString json("{"
"\"encoding\" : \"UTF-8\","
"\"plug-ins\" : ["
"\"python\","
"\"c++\","
"\"ruby\""
"],"
"\"indent\" : { \"length\" : 3, \"use_space\" : true }"
"}");
QJsonParseError error;
QJsonDocument jsonDocument = QJsonDocument::fromJson(json.toUtf8(), &error);
if (error.error == QJsonParseError::NoError) {
if (jsonDocument.isObject()) {
QVariantMap result = jsonDocument.toVariant().toMap();
qDebug() << "encoding:" << result["encoding"].toString();
qDebug() << "plugins:";
foreach (QVariant plugin, result["plug-ins"].toList()) {
qDebug() << "\t-" << plugin.toString();
}
QVariantMap nestedMap = result["indent"].toMap();
qDebug() << "length:" << nestedMap["length"].toInt();
qDebug() << "use_space:" << nestedMap["use_space"].toBool();
}
} else {
qFatal(error.errorString().toUtf8().constData());
exit(1);
}
~~~
這段代碼與前面的幾乎相同。`QJsonDocument::fromJson()`可以由`QByteArray`對象構造一個`QJsonDocument`對象,用于我們的讀寫操作。這里我們傳入一個`QJsonParseError`對象的指針作為第二個參數,用于獲取解析的結果。如果`QJsonParseError::error()`的返回值為`QJsonParseError::NoError`,說明一切正常,則繼續以`QVariant`的格式進行解析(由于我們知道這是一個 JSON 對象,因此只判斷了`isObject()`。當處理未知的 JSON?時,或許應當將所有的情況都考慮一邊,包括`isObject()`、`isArray()`以及`isEmpty()`)。
也就是說,如果需要使用`QJsonDocument`處理 JSON 文檔,我們只需要使用下面的代碼模板:
~~~
// 1. 創建 QJsonParseError 對象,用來獲取解析結果
QJsonParseError error;
// 2. 使用靜態函數獲取 QJsonDocument 對象
QJsonDocument jsonDocument = QJsonDocument::fromJson(json.toUtf8(), &error);
// 3. 根據解析結果進行處理
if (error.error == QJsonParseError::NoError) {
if (!(jsonDocument.isNull() || jsonDocument.isEmpty())) {
if (jsonDocument.isObject()) {
// ...
} else if (jsonDocument.isArray()) {
// ...
}
}
} else {
// 檢查錯誤類型
}
~~~
將`QVariant`對象生成 JSON 文檔也很簡單:
~~~
QVariantList people;
QVariantMap bob;
bob.insert("Name", "Bob");
bob.insert("Phonenumber", 123);
QVariantMap alice;
alice.insert("Name", "Alice");
alice.insert("Phonenumber", 321);
people << bob << alice;
QJsonDocument jsonDocument = QJsonDocument::fromVariant(people);
if (!jsonDocument.isNull()) {
qDebug() << jsonDocument.toJson();
~~~
這里我們仍然使用的是`QJsonDocument`,只不過這次我們需要使用`QJsonDocument::fromVariant()`函數獲取`QJsonDocument`對象。`QJsonDocument`也可以以二進制格式讀取對象,比如`QJsonDocument::fromBinaryData()`和`QJsonDocument::fromRawData()`函數。當我們成功獲取到`QJsonDocument`對象之后,可以使用`toJson()`生成 JSON 文檔。
以上介紹了當我們有一個 JSON 文檔時,如何使用`QJsonDocument`進行處理。如果我們沒有 JSON 文檔,那么我們可以使用`QJsonDocument`的`setArray()`和`setObject()`函數動態設置該對象,然后再生成對應的 JSON 格式文檔。不過這部分需求比較罕見,因為我們直接可以從`QVariant`值類型獲取。
Qt5 提供的 JSON 類庫直接支持[隱式數據共享](http://www.devbean.net/2013/01/qt-study-road-2-implicit-sharing/),因此我們不需要為復制的效率擔心。
- (1)序
- (2)Qt 簡介
- (3)Hello, world!
- (4)信號槽
- (5)自定義信號槽
- (6)Qt 模塊簡介
- (7)MainWindow 簡介
- (8)添加動作
- (9)資源文件
- (10)對象模型
- (11)布局管理器
- (12)菜單欄、工具欄和狀態欄
- (13)對話框簡介
- (14)對話框數據傳遞
- (15)標準對話框 QMessageBox
- (16)深入 Qt5 信號槽新語法
- (17)文件對話框
- (18)事件
- (19)事件的接受與忽略
- (21)事件過濾器
- (22)事件總結
- (23)自定義事件
- (24)Qt 繪制系統簡介
- (25)畫刷和畫筆
- (26)反走樣
- (27)漸變
- (28)坐標系統
- (29)繪制設備
- (30)Graphics View Framework
- (31)貪吃蛇游戲(1)
- (32)貪吃蛇游戲(2)
- (33)貪吃蛇游戲(3)
- (34)貪吃蛇游戲(4)
- (35)文件
- (36)二進制文件讀寫
- (37)文本文件讀寫
- (38)存儲容器
- (39)遍歷容器
- (40)隱式數據共享
- (41)model/view 架構
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)視圖和委托
- (47)視圖選擇
- (48)QSortFilterProxyModel
- (49)自定義只讀模型
- (50)自定義可編輯模型
- (51)布爾表達式樹模型
- (52)使用拖放
- (53)自定義拖放數據
- (54)剪貼板
- (55)數據庫操作
- (56)使用模型操作數據庫
- (57)可視化顯示數據庫數據
- (58)編輯數據庫外鍵
- (59)使用流處理 XML
- (60)使用 DOM 處理 XML
- (61)使用 SAX 處理 XML
- (62)保存 XML
- (63)使用 QJson 處理 JSON
- (64)使用 QJsonDocument 處理 JSON
- (65)訪問網絡(1)
- (66)訪問網絡(2)
- (67)訪問網絡(3)
- (68)訪問網絡(4)
- (69)進程
- (70)進程間通信
- (71)線程簡介
- (72)線程和事件循環
- (73)Qt 線程相關類
- (74)線程和 QObject
- (75)線程總結
- (76)QML 和 QtQuick 2
- (77)QML 語法
- (78)QML 基本元素
- (79)QML 組件
- (80)定位器
- (81)元素布局
- (82)輸入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)動態視圖
- (86)視圖代理
- (87)模型-視圖高級技術
- (88)Canvas
- (89)Canvas(續)