当前位置:   article > 正文

Qt JSON详解二_qt4 json

qt4 json

一、JSON概述

JSON( JavaScript Object Notation,对象表示法) 是一种轻量级的数据交换格式。 它基于 ECMAScript 的一个子集。许多编程语言都很容易找到J SON 解析器和 JSON 库。 JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。不同语言的不同 json 库对 JSON 标准的支持不尽相同,为了能让尽可能多的 JSON 库都能正常解析和生成 JSON ,定义 JSON 的规范很重要,推荐一个 JSON 规范《Google - JSON风格指南》。

二、常用的JSON库

json.org 中介绍了 JSON 在各种语言中的应用,在 C/C++ 中比较常用的 JSON 库主要有以下几个:

  • nlohmann:是一个用于解析 JSON 的开源 C++ 库,口碑一流,使用非常方便直观,是很多 C++ 程序员的首选。

  • RapidJSON:腾讯员工开源的一个以高性能著称的 JSON 库,用的人也很多,缺点就是接口比较难用,不太友好。

  • cJSON:是一个超轻巧,携带方便,只有两个文件 cJSON.h 和 cJSON.cpp,简单的可以作为 ANSI-C 标准的 JSON 解析器,缺点是容易造成内存泄漏,也不支持线程安全。

  • QJson:是一个基于 Qt4 的开发包用来将 JSON 数据解析成 QVariant 对象,JSON 的数组将被映射为QVariantList 实例,而其他对象映射为 QVariantMap 实例,适合用在 Qt 开发平台上。

  • json-cJsonCpp等。

这里只简单讲解下 Qt 中对 JSON 的生成与解析,Qt5 以前的版本,可以使用 QJson 库,需要单独下载、编译,才能使用。到了 Qt5,提供了专门的 QJsonDocument 及其相关类来读和写 JSON 文档。

三、JSON 常用类

首先,JSON 的解析和构建都要包含如下头文件,下面一个个介绍下:

  1. #include <QJsonDocument>
  2. #include <QJsonArray>
  3. #include <QJsonObject>


3.1 QJsonDocument

QJsonDocument 类用于读和写 JSON 文档。

一个 JSON 文档可以使用 QJsonDocument::fromJson() 从基于文本的表示转化为 QJsonDocument, toJson(JsonFormat format = Indented) 则可以反向转化为文本,其中,format主要有两种格式,一种是人们可读的格式,一种是紧凑的格式。

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

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

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


3.2 QJsonArray

QJsonArray 类封装了一个 JSON 数组。

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

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


3.3 QJsonObject

QJsonObject 类封装了一个 JSON 对象。

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

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


3.4 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() 等函数转化成相应的存储类型。


3.5 QJsonParseError

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

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

四、JSON 对象的构建与解析

一个简单的 JSON 对象:

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

构建比较简单,由于是一个对象,只需要用 QJsonObject 即可:

  1. // 构建 JSON 对象
  2. QJsonObject jsonObj;
  3. jsonObj.insert("Name", "Qt");
  4. jsonObj.insert("From", 1991);
  5. jsonObj.insert("Cross Platform", true);
  6. // 构建 JSON 文档
  7. QJsonDocument document;
  8. document.setObject(jsonObj);
  9. QByteArray byteArray = document.toJson(QJsonDocument::Compact);
  10. QString strJson(byteArray);
  11. qDebug() << strJson;

解析如下:

  1. QJsonParseError jsonError;
  2. QJsonDocument doucment = QJsonDocument::fromJson(byteArray, &jsonError); // 转化为 JSON 文档
  3. if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误
  4. if (doucment.isObject()) { // JSON 文档为对象
  5. QJsonObject object = doucment.object(); // 转化为对象
  6. if (object.contains("Name")) { // 包含指定的 key
  7. QJsonValue value = object.value("Name"); // 获取指定 key 对应的 value
  8. if (value.isString()) { // 判断 value 是否为字符串
  9. QString strName = value.toString(); //value 转化为字符串
  10. qDebug() << "Name : " << strName;
  11. }
  12. }
  13. if (object.contains("From")) {
  14. QJsonValue value = object.value("From");
  15. if (value.isDouble()) {
  16. int nFrom = value.toVariant().toInt();
  17. qDebug() << "From : " << nFrom;
  18. }
  19. }
  20. if (object.contains("Cross Platform")) {
  21. QJsonValue value = object.value("Cross Platform");
  22. if (value.isBool()) {
  23. bool bCrossPlatform = value.toBool();
  24. qDebug() << "CrossPlatform : " << bCrossPlatform;
  25. }
  26. }
  27. }
  28. }

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

五、JSON 数组的构建与解析

一个简单的 JSON 数组:

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

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

  1. // 构建 JSON 数组
  2. QJsonArray json;
  3. json.append("Qt");
  4. json.append(5.7);
  5. json.append(true);
  6. // 构建 JSON 文档
  7. QJsonDocument document;
  8. document.setArray(json);
  9. QByteArray byteArray = document.toJson(QJsonDocument::Compact);
  10. QString strJson(byteArray);
  11. qDebug() << strJson;

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

  1. QJsonParseError jsonError;
  2. QJsonDocument doucment = QJsonDocument::fromJson(byteArray, &jsonError); // 转化为 JSON 文档
  3. if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误
  4. if (doucment.isArray()) { // JSON 文档为数组
  5. QJsonArray array = doucment.array(); // 转化为数组
  6. int nSize = array.size(); // 获取数组大小
  7. for (int i = 0; i < nSize; ++i) { // 遍历数组
  8. QJsonValue value = array.at(i);
  9. if (value.type() == QJsonValue::String) {
  10. QString strName = value.toString();
  11. qDebug() << strName;
  12. }
  13. if (value.type() == QJsonValue::Double) {
  14. double dVersion = value.toDouble();
  15. qDebug() << dVersion;
  16. }
  17. if (value.type() == QJsonValue::Bool) {
  18. bool bCrossPlatform = value.toBool();
  19. qDebug() << bCrossPlatform;
  20. }
  21. }
  22. }
  23. }

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

六、复杂的JSON的构建与解析

构造一个复杂的 JSON 对象:

  1. {
  2. "Company": "Digia",
  3. "From": 1991,
  4. "Name": "Qt",
  5. "Page": {
  6. "Developers": "https://www.qt.io/developers/",
  7. "Download": "https://www.qt.io/download/",
  8. "Home": "https://www.qt.io/"
  9. },
  10. "Version": [
  11. 4.8,
  12. 5.2,
  13. 5.7
  14. ]
  15. }

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

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

  1. // 构建 Json 数组 - Version
  2. QJsonArray versionArray;
  3. versionArray.append(4.8);
  4. versionArray.append(5.2);
  5. versionArray.append(5.7);
  6. // 构建 Json 对象 - Page
  7. QJsonObject pageObject;
  8. pageObject.insert("Home", "https://www.qt.io/");
  9. pageObject.insert("Download", "https://www.qt.io/download/");
  10. pageObject.insert("Developers", "https://www.qt.io/developers/");
  11. // 构建 Json 对象
  12. QJsonObject json;
  13. json.insert("Name", "Qt");
  14. json.insert("Company", "Digia");
  15. json.insert("From", 1991);
  16. json.insert("Version", QJsonValue(versionArray));
  17. json.insert("Page", QJsonValue(pageObject));
  18. // 构建 Json 文档
  19. QJsonDocument document;
  20. document.setObject(json);
  21. QByteArray byteArray = document.toJson(QJsonDocument::Compact);
  22. QString strJson(byteArray);
  23. qDebug() << strJson;

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

  1. QJsonParseError jsonError;
  2. QJsonDocument doucment = QJsonDocument::fromJson(byteArray, &jsonError); // 转化为 JSON 文档
  3. if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误
  4. if (doucment.isObject()) { // JSON 文档为对象
  5. QJsonObject object = doucment.object(); // 转化为对象
  6. if (object.contains("Name")) {
  7. QJsonValue value = object.value("Name");
  8. if (value.isString()) {
  9. QString strName = value.toString();
  10. qDebug() << "Name : " << strName;
  11. }
  12. }
  13. if (object.contains("Company")) {
  14. QJsonValue value = object.value("Company");
  15. if (value.isString()) {
  16. QString strCompany = value.toString();
  17. qDebug() << "Company : " << strCompany;
  18. }
  19. }
  20. if (object.contains("From")) {
  21. QJsonValue value = object.value("From");
  22. if (value.isDouble()) {
  23. int nFrom = value.toVariant().toInt();
  24. qDebug() << "From : " << nFrom;
  25. }
  26. }
  27. if (object.contains("Version")) {
  28. QJsonValue value = object.value("Version");
  29. if (value.isArray()) { // Version 的 value 是数组
  30. QJsonArray array = value.toArray();
  31. int nSize = array.size();
  32. for (int i = 0; i < nSize; ++i) {
  33. QJsonValue value = array.at(i);
  34. if (value.isDouble()) {
  35. double dVersion = value.toDouble();
  36. qDebug() << "Version : " << dVersion;
  37. }
  38. }
  39. }
  40. }
  41. if (object.contains("Page")) {
  42. QJsonValue value = object.value("Page");
  43. if (value.isObject()) { // Pagevalue 是对象
  44. QJsonObject obj = value.toObject();
  45. if (obj.contains("Home")) {
  46. QJsonValue value = obj.value("Home");
  47. if (value.isString()) {
  48. QString strHome = value.toString();
  49. qDebug() << "Home : " << strHome;
  50. }
  51. }
  52. if (obj.contains("Download")) {
  53. QJsonValue value = obj.value("Download");
  54. if (value.isString()) {
  55. QString strDownload = value.toString();
  56. qDebug() << "Download : " << strDownload;
  57. }
  58. }
  59. if (obj.contains("Developers")) {
  60. QJsonValue value = obj.value("Developers");
  61. if (value.isString()) {
  62. QString strDevelopers = value.toString();
  63. qDebug() << "Developers : " << strDevelopers;
  64. }
  65. }
  66. }
  67. }
  68. }
  69. }

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


七、Qt 常用JSON解析示例

JSON的解析要对照JSON字符串来理解,关于JSON字符串的介绍,可以参考JSON简介

首先,解析和构建都要包含如下头文件:

  1. #include <QJsonDocument>
  2. #include <QJsonObject>
  3. #include <QJsonArray>

示例1:和风天气实时数据

这个 JSON 字符串中 HeWeather6 键的值是一个数组,数组内只有 1 个 JSON 对象,这个对象里又嵌套了几个 JSON 对象。

  1. {
  2. "HeWeather6": [{
  3. "basic": {
  4. "cid": "CN101010700",
  5. "parent_city": "北京",
  6. "cnty": "中国",
  7. },
  8. "status": "ok",
  9. }]
  10. }

主要是 JSON 的多层嵌套的解析。解析函数:

  1. int Parse_HeWeather_Now_Json(void)
  2. {
  3. QJsonParseError err_rpt;
  4. QJsonDocument root_Doc = QJsonDocument::fromJson(he_now_json, &err_rpt); // 字符串格式化为JSON
  5. if(err_rpt.error != QJsonParseError::NoError)
  6. {
  7. qDebug() << "JSON格式错误";
  8. return -1;
  9. }
  10. else // JSON格式正确
  11. {
  12. //qDebug() << "JSON格式正确:\n" << root_Doc;
  13. QJsonObject root_Obj = root_Doc.object();
  14. QJsonValue weather_Value = root_Obj.value("HeWeather6"); // HeWeather6键的值,是一个数组
  15. if(weather_Value.isArray()) // 可省略
  16. {
  17. QJsonObject weather_Obj = weather_Value.toArray().at(0).toObject(); // HeWeather6数组就含有一个元素0
  18. /* basic键信息 */
  19. QJsonObject basic_Obj = weather_Obj.value("basic").toObject();
  20. QString cid = basic_Obj.value("cid").toString();
  21. QString parent_city = basic_Obj.value("parent_city").toString();
  22. QString cnty = basic_Obj.value("cnty").toString();
  23. QString basic_info = cid + " " + parent_city + " " + cnty;
  24. qDebug() << basic_info;
  25. QString status = "解析状态:" + weather_Obj.value("status").toString(); //"ok"
  26. qDebug() << status;
  27. }
  28. return 0;
  29. }

示例2:心知天气实时数据

这个字符串和上面那个一样,都是数组元素是 JSON 对象,对象的值又是一个 JSON 对象。

  1. {
  2. "results": [{
  3. "location": {
  4. "id": "WX4FBXXFKE4F",
  5. "name": "北京",
  6. "country": "CN",
  7. "path": "北京,北京,中国",
  8. "timezone": "Asia/Shanghai",
  9. "timezone_offset": "+08:00"
  10. },
  11. "now": {
  12. "text": "晴",
  13. "code": "1",
  14. "temperature": "-7"
  15. },
  16. "last_update": "2018-12-06T22:05:00+08:00"
  17. }]
  18. }

解析函数:

  1. int Parse_Seniverse_Now_Json(void)
  2. {
  3. QJsonParseError err_rpt;
  4. QJsonDocument root_Doc = QJsonDocument::fromJson(seniverse_now_json, &err_rpt); // 字符串格式化为JSON
  5. if(err_rpt.error != QJsonParseError::NoError)
  6. {
  7. qDebug() << "JSON格式错误";
  8. return -1;
  9. }
  10. else // JSON格式正确
  11. {
  12. //qDebug() << "JSON格式正确:\n" << root_Doc;
  13. QJsonObject root_Obj = root_Doc.object();
  14. QJsonValue result_Value = root_Obj.value("results");
  15. if(result_Value.isArray())
  16. {
  17. QJsonObject result_Obj = result_Value.toArray().at(0).toObject();
  18. QString last_update = result_Obj.value("last_update").toString();
  19. qDebug() << last_update;
  20. /* location键的值 */
  21. QJsonObject location_Obj = result_Obj.value("location").toObject();
  22. QString id = location_Obj.value("id").toString();
  23. QString name = location_Obj.value("name").toString();
  24. QString timezone = location_Obj.value("timezone").toString();
  25. QString path = location_Obj.value("path").toString();
  26. QString loc_str = id + " " + name + " " + timezone + " " + path ;
  27. qDebug() << loc_str;
  28. /* now键 */
  29. QJsonObject now_Obj = result_Obj.value("now").toObject();
  30. QString code = "天气代码: " + now_Obj.value("code").toString();
  31. QString temperature = "当前温度:" + now_Obj.value("temperature").toString();
  32. QString text = "天气:" + now_Obj.value("text").toString();
  33. qDebug() << code << temperature << text;
  34. }
  35. }
  36. return 0;
  37. }

示例3:获取ID

JSON字符串为:

  1. {
  2. "data": {
  3. "list":[
  4. {"id":"20200602221529"},
  5. {"id":"20200602203158"},
  6. {"id":"20200602175752"}
  7. ],
  8. "pagecnt":5,
  9. "pageindex":2
  10. },
  11. "result":0,
  12. "type":25
  13. }

解析函数:

  1. QJsonParseError parseJsonErr;
  2. // 转化为JSON文档
  3. QJsonDocument jsonDoc = QJsonDocument::fromJson(response.toUtf8(), &parseJsonErr);
  4. // 解析未发生错误
  5. if(parseJsonErr.error == QJsonParseError::NoError)
  6. {
  7. QJsonObject rootObj = jsonDoc.object(); // 转化为root对象
  8. QJsonValue rootValue = rootObj.value("data"); // 获取指定key对应的value,
  9. QJsonObject arrObject = rootValue.toObject(); // 再将值转换为obj:上一级key对应的值实际为数组对象
  10. QJsonValue arrValue = arrObject.value("list");
  11. if(arrValue.isArray()) // 判断获取的QJsonValue对象是不是数组结构
  12. {
  13. QJsonArray array = arrValue.toArray();
  14. for(int i=0;i<array.size();i++)
  15. {
  16. QJsonValue idValue = array.at(i);
  17. QJsonObject idObject = idValue.toObject();
  18. QString id = idObject["id"].toString();
  19. qDebug() <<"id=" <<id;
  20. }
  21. }
  22. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/1016480
推荐阅读
相关标签
  

闽ICP备14008679号