Qt中的JSON操作

JSON(JavaScript Object Notation,js對象標記)是一種輕量級的數據交換格式。它基於ECMAScript的一個子集,使用完全獨立於編程語言的文本格式來存儲和表示數據。簡潔和清晰的的層次結構使得JSON成爲理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成,並有效的提升網絡傳輸效率。關於JSON的更多解釋,請參看JSON官網

在Qt庫中,爲JSON的相關操作提供了完整的類支持,包括QJsonValue,QJsonObject,QJsonArray,QJsonDocument和QJsonParseError。其中,QJsonValue類表示json格式中的一個值;QJsonObject表示一個json對象;QJsonArray顧名思義表示一個json數組;QJsonDocument主要用來讀寫json文檔;而QJsonParseError是用來表示json解析過程中出現的錯誤的方便類。下面,我們就來看看這些類的詳細信息。

QJsonValue

QJsonValue類封裝了一個json格式中的值。該值可以是如下6中基本類型:

  • bool QJsonValue::Bool
  • double QJsonValue::Double
  • string QJsonValue::String
  • array QJsonValue::Array
  • object QJsonValue::Object
  • null QJsonValue::Null
一個QJsonValue可以表示上面任何一種數據類型。此外,QJsonValue還有一個特殊的標誌用來表示未定義的值。可以使用isUndefined()函數來進行判斷。而一個QJsonValue中存儲的類型可以通過type()或isBool(),isString()之類的函數進行查詢。同樣,QJsonValue中存儲的值可以通過toBool(),toString()等函數轉換到具體的類型。
QJsonValue中存儲的值在內部是強類型的,並且和QVariant相反,它不會嘗試進行任何的隱式類型轉換。這意味着將QJsonValue轉換成一個不是它存儲的類型,將返回一個該類型的模型構造函數返回的值。
其實,說到QJsonValue,還有另一個類要說,QJsonValueRef,該類是一個對於QJsonArray和QJsonObject來說的一個幫助類。當你獲得一個QJsonValueRef類的對象後,你可以把它當做一個QJsonValue對象的應用來使用。如果你向他賦值,該值會實際作用到底層的QJsonArray或者QJsonObject對象中的元素上。而要想使用該類,可以使用一下的兩個方法:
  • QJsonArray::operator[](int i)
  • QJsonObject::operator[](const QString& key)const;
下面來看一下QJsonValue的構造函數:
[cpp] view plain copy
  1. QJsonValue(Type type = Null)  
  2. QJsonValue(bool b)  
  3. QJsonValue(double n)  
  4. QJsonValue(int n)  
  5. QJsonValue(qint64 n)  
  6. QJsonValue(const QString &s)  
  7. QJsonValue(QLatin1String s)  
  8. QJsonValue(const char *s)  
  9. QJsonValue(const QJsonArray &a)  
  10. QJsonValue(const QJsonObject &o)  
  11. QJsonValue(const QJsonValue &other)  
可以看到,該類主要是對基本類型的一個包裝。

QJsonObject
QJsonObject類封裝了一個json對象。一個json對象是一個鍵值對的列表,其中key是唯一的字符串,而值就是一個我們上面講到的QJsonValue。一個QJsonObject的對象可以轉換到QVariantMap,要可以由QVariantMap轉換得到。
我們可以使用size()函數來查詢一個QJsonObject中存儲的鍵值對的個數;使用insert()和remove()來插入或從中刪除鍵值對;還可以使用標準的C++迭代器來遍歷它。
QJsonObject類是一個隱式共享類。
其構造函數如下:
[cpp] view plain copy
  1. QJsonObject()  
  2. QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)  
  3. QJsonObject(const QJsonObject &other)  
我們可以使用初始化列表來快速的構建一個QJsonObject對象。如下:
[cpp] view plain copy
  1. QJsonObject object  
  2. {  
  3.     {"property1", 1},  
  4.     {"property2", 2}  
  5. };  
如此之外,比較常用的就是insert()函數了:
[cpp] view plain copy
  1. iterator QJsonObject::insert(const QString &key, const QJsonValue &value)  
一般,我們可以先定義一個空的QJsonObject對象,然後使用該函數向其中插入需要的鍵值對。如果新插入的key已存在,那麼會進行替換。
下面,我們通過一個例子還使用該類構造如下json字符串:{"name":"lily", "age":23, "addr":{"city":"xxx", "province":"yyy"}}
代碼如下:
[cpp] view plain copy
  1. #include <QCoreApplication>  
  2. #include <QDebug>  
  3. #include <QJsonObject>  
  4.   
  5. int main(int argc, char *argv[])  
  6. {  
  7.     QCoreApplication a(argc, argv);  
  8.   
  9.     QJsonObject obj;  
  10.     obj.insert("name""lily");  
  11.     obj.insert("age", 23);  
  12.     QJsonObject addr;  
  13.     addr.insert("city""guangzhou");  
  14.     addr.insert("province""guangdong");  
  15.     obj.insert("addr", addr);  
  16.     qDebug() << obj;  
  17.   
  18.     return a.exec();  
  19. }  
我們先構建了一個QJsonObject對象obj,然後向其中插入姓名和年齡鍵值對;因爲地址又是一個QJsonObject,所以我們又構建了addr對象,向其中插入城市和省份,最後,將該QJsonObject做爲地址鍵值對的值,插入到obj中。打印結果如下:


QJsonArray
顧名思義,QJsonArray封裝了一個JSON數組。一個JSON數組是一個值的列表。我們可以向這個列表中插入或刪除QJsonValue。
同時,我們可以把一個QVariantList轉換成一個QJsonArray。也可以使用標準C++迭代器對它進行遍歷。
其構造函數如下:
[cpp] view plain copy
  1. QJsonArray()  
  2. QJsonArray(std::initializer_list<QJsonValue> args)  
  3. QJsonArray(const QJsonArray &other)  
我們也可以像上面那樣,使用一個初始化列表來構建一個QJsonArray對象:
[cpp] view plain copy
  1. QJsonArray array = { 1, 2.2, QString() };  
在此我們只使用了單個的值,沒有使用鍵值對。其實,這樣的json對象,一般我們就稱爲數組。
和QJsonObject一樣,我們一般也是通過它的insert()函數來生成我們需要的json數組:
[cpp] view plain copy
  1. void insert(int i, const QJsonValue &value)  
  2. iterator insert(iterator before, const QJsonValue &value)  
下面,我們繼續上面的例子,來生成一個表示人物信息的列表。代碼如下:
[cpp] view plain copy
  1. #include <QCoreApplication>  
  2. #include <QDebug>  
  3. #include <QJsonObject>  
  4. #include <QJsonArray>  
  5.   
  6. int main(int argc, char *argv[])  
  7. {  
  8.     QCoreApplication a(argc, argv);  
  9.   
  10.     QJsonObject obj1;  
  11.     obj1.insert("name""lily");  
  12.     obj1.insert("age", 23);  
  13.     QJsonObject addr1;  
  14.     addr1.insert("city""guangzhou");  
  15.     addr1.insert("province""guangdong");  
  16.     obj1.insert("addr", addr1);  
  17.     qDebug() << obj1;  
  18.   
  19.     QJsonObject obj2;  
  20.     obj2.insert("name""tom");  
  21.     obj2.insert("age", 24);  
  22.     QJsonObject addr2;  
  23.     addr2.insert("city""shenzhen");  
  24.     addr2.insert("province""guangdong");  
  25.     obj2.insert("addr", addr2);  
  26.     qDebug() << obj2;  
  27.   
  28.     QJsonObject obj3;  
  29.     obj3.insert("name""jerry");  
  30.     obj3.insert("age", 24);  
  31.     QJsonObject addr3;  
  32.     addr3.insert("city""foshan");  
  33.     addr3.insert("province""guangdong");  
  34.     obj3.insert("addr", addr3);  
  35.     qDebug() << obj3;  
  36.   
  37.     QJsonArray array;  
  38.     array.push_back(obj1);  
  39.     array.push_back(obj2);  
  40.     array.push_back(obj3);  
  41.     qDebug() << array;  
  42.   
  43.     return a.exec();  
  44. }  

在此,我們只是簡單的構建了三個人物的QJsonObject對象,然後將它們放入一個QJsonArray中。輸入結果如下:


QJsonDocument
QJsonDocument類提供了讀寫JSON文檔的方法。QJsonDocument類包裝了一個完整的JSON 文檔,我們可以以utf-8編碼的文本格式和Qt自己的二進制格式來操作該文檔。一個JSON文檔可以使用QJsonDocument::fromJson()函數轉換json文本字符串來得到。而toJson()可以將其轉換成文本。這個解析器是非常快速和高效的,Qt也是使用它來將JSON對象轉換成其二進制表示的。解析得到的文檔可以使用isNull()來判斷是否有效。還可以使用isArray()和isObject()函數來判斷該文檔所包含的是否是數據或json對象。如果是,可以使用array()或object()函數還獲得其中的對象或數組。
其構造函數如下:
[cpp] view plain copy
  1. QJsonDocument()  
  2. QJsonDocument(const QJsonObject &object)  
  3. QJsonDocument(const QJsonArray &array)  
  4. QJsonDocument(const QJsonDocument &other)  

除了構造函數外,該類還提供了兩個轉換函數,可以將json文檔序列化爲二進制對象,然後我們就可以將該對象存儲到文件中,或發送到網絡上。
[cpp] view plain copy
  1. QByteArray toBinaryData() const  
  2. QByteArray toJson(JsonFormat format = Indented) const  

下面,我們就使用該類將我們上面生成的json數組寫入到文件中:
代碼如下:
[cpp] view plain copy
  1. #include <QCoreApplication>  
  2. #include <QDebug>  
  3. #include <QJsonObject>  
  4. #include <QJsonArray>  
  5. #include <QFile>  
  6. #include <QJsonDocument>  
  7.   
  8. int main(int argc, char *argv[])  
  9. {  
  10.     QCoreApplication a(argc, argv);  
  11.   
  12.     QJsonObject obj1;  
  13.     obj1.insert("name""lily");  
  14.     obj1.insert("age", 23);  
  15.     QJsonObject addr1;  
  16.     addr1.insert("city""guangzhou");  
  17.     addr1.insert("province""guangdong");  
  18.     obj1.insert("addr", addr1);  
  19.     qDebug() << obj1;  
  20.   
  21.     QJsonObject obj2;  
  22.     obj2.insert("name""tom");  
  23.     obj2.insert("age", 24);  
  24.     QJsonObject addr2;  
  25.     addr2.insert("city""shenzhen");  
  26.     addr2.insert("province""guangdong");  
  27.     obj2.insert("addr", addr2);  
  28.     qDebug() << obj2;  
  29.   
  30.     QJsonObject obj3;  
  31.     obj3.insert("name""jerry");  
  32.     obj3.insert("age", 24);  
  33.     QJsonObject addr3;  
  34.     addr3.insert("city""foshan");  
  35.     addr3.insert("province""guangdong");  
  36.     obj3.insert("addr", addr3);  
  37.     qDebug() << obj3;  
  38.   
  39.     QJsonArray array;  
  40.     array.push_back(obj1);  
  41.     array.push_back(obj2);  
  42.     array.push_back(obj3);  
  43.     qDebug() << array;  
  44.   
  45.     QJsonDocument jsonDoc(array);  
  46.     QByteArray ba = jsonDoc.toJson();  
  47.     QFile file("result.json");  
  48.     if(!file.open(QIODevice::WriteOnly))  
  49.     {  
  50.         qDebug() << "write json file failed";  
  51.         return 0;  
  52.     }  
  53.     file.write(ba);  
  54.     file.close();  
  55.   
  56.     return a.exec();  
  57. }  
我們先使用QJsonArray構建出一個QJsonDocument對象,然後調用其toJson()方法,將該json文檔轉換成一個字節數組。注意,toJson()函數會接受一個格式化參數:
[cpp] view plain copy
  1. QByteArray QJsonDocument::toJson(JsonFormat format = Indented) const  
其中,format主要有兩種格式,一種是人們可讀的格式,一種是緊湊的格式。分別描述如下表:
Constant Value Description
QJsonDocument::Indented 0 定義人們可讀的輸出格式,如下:
{
"Array":[
true,
999,
"string"
],
"key": "value",
"null": null
}
QJsonDocument::Compact 1 定義一個緊湊的輸出格式,如下:
{"Array": [true, 999, "string"], "key": "value", "null":null}

toJson()函數默認使用Indented,一縮進的形式生成人們可讀的json文件。
運行該程序後,在編譯目錄查看生成的json文件。結果如下:


當然,除了將json對象寫入到文件中,QJsonDocument還提供了幾個靜態函數,將從文件中讀取出的原始數據或json字符串轉換成一個QJsonDocument對象。函數聲明信息如下:
[cpp] view plain copy
  1. QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate)  
  2. QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR)  
  3. QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate)  
  4. QJsonDocument fromVariant(const QVariant &variant)  

下面,我們就使用這些函數,將我們寫入到文件中的json對象再讀出來,並生成一個QJsonDocument對象。
代碼如下:
[cpp] view plain copy
  1. #include <QCoreApplication>  
  2. #include <QDebug>  
  3. #include <QFile>  
  4. #include <QJsonDocument>  
  5.   
  6. int main(int argc, char *argv[])  
  7. {  
  8.     QCoreApplication a(argc, argv);  
  9.   
  10.     QFile file("result.json");  
  11.     if(!file.open(QIODevice::ReadOnly))  
  12.     {  
  13.         qDebug() << "read json file failed";  
  14.         return 0;  
  15.     }  
  16.     QByteArray ba = file.readAll();  
  17.     qDebug() << "讀出的數據如下:";  
  18.     qDebug() << ba;  
  19.     QJsonParseError e;  
  20.     QJsonDocument jsonDoc = QJsonDocument::fromJson(ba, &e);  
  21.     if(e.error == QJsonParseError::NoError && !jsonDoc.isNull())  
  22.     {  
  23.         qDebug() << jsonDoc;  
  24.     }  
  25.   
  26.     return a.exec();  
  27. }  

在此,因爲我們從文件中讀出的是一個json形式的字符串,所以可以使用fromJson()函數,將其轉換成一個QJsonDocument對象。同時,在調用fromJson()函數時,我們還爲它傳入了一個QJsonParseError對象,用來接收解析json字符串的過程中,有可能發生的錯誤信息。
代碼運行如下:


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