1. 程式人生 > >Qt中的JSON操作

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的建構函式:

 
  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類是一個隱式共享類。

其建構函式如下:

 
  1. QJsonObject()

  2. QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)

  3. QJsonObject(const QJsonObject &other)

我們可以使用初始化列表來快速的構建一個QJsonObject物件。如下:

 
  1. QJsonObject object

  2. {

  3. {"property1", 1},

  4. {"property2", 2}

  5. };

如此之外,比較常用的就是insert()函數了:

iterator QJsonObject::insert(const QString &key, const QJsonValue &value)

一般,我們可以先定義一個空的QJsonObject物件,然後使用該函式向其中插入需要的鍵值對。如果新插入的key已存在,那麼會進行替換。

下面,我們通過一個例子還使用該類構造如下json字串:{"name":"lily", "age":23, "addr":{"city":"xxx", "province":"yyy"}}

程式碼如下:

 
  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++迭代器對它進行遍歷。

其建構函式如下:

 
  1. QJsonArray()

  2. QJsonArray(std::initializer_list<QJsonValue> args)

  3. QJsonArray(const QJsonArray &other)

我們也可以像上面那樣,使用一個初始化列表來構建一個QJsonArray物件:

QJsonArray array = { 1, 2.2, QString() };

在此我們只使用了單個的值,沒有使用鍵值對。其實,這樣的json物件,一般我們就稱為陣列。

和QJsonObject一樣,我們一般也是通過它的insert()函式來生成我們需要的json陣列:

 
  1. void insert(int i, const QJsonValue &value)

  2. iterator insert(iterator before, const QJsonValue &value)

  3.  

下面,我們繼續上面的例子,來生成一個表示人物資訊的列表。程式碼如下:

 
  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()函式還獲得其中的物件或陣列。

其建構函式如下:

 
  1. QJsonDocument()

  2. QJsonDocument(const QJsonObject &object)

  3. QJsonDocument(const QJsonArray &array)

  4. QJsonDocument(const QJsonDocument &other)

 

除了建構函式外,該類還提供了兩個轉換函式,可以將json文件序列化為二進位制物件,然後我們就可以將該物件儲存到檔案中,或傳送到網路上。

 
  1. QByteArray toBinaryData() const

  2. QByteArray toJson(JsonFormat format = Indented) const

  3.  

 

下面,我們就使用該類將我們上面生成的json陣列寫入到檔案中:

程式碼如下:

 
  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()函式會接受一個格式化引數:

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物件。函式宣告資訊如下:

 
  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)

  5.  

 

下面,我們就使用這些函式,將我們寫入到檔案中的json物件再讀出來,並生成一個QJsonDocument物件。

程式碼如下:

 
  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字串的過程中,有可能發生的錯誤資訊。

程式碼執行如下:

--------------------- 本文來自 求道玉 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/amnes1a/article/details/68957112?utm_source=copy