QT解析Json

原始数据如下:

{
  "cityid": "101130101",
  "update_time": "2019-04-11 11:30:00",
  "city": "乌鲁木齐",
  "cityEn": "wulumuqi",
  "country": "中国",
  "countryEn": "China",
  "data": [
    {
      "day": "11日(今天)",
      "date": "2019-04-11",
      "week": "星期四",
      "wea": "多云",
      "wea_img": "yun",
      "air": 52,
      "humidity": 16,
      "air_level": "良",
      "air_tips": "空气好,可以外出活动,除极少数对污染物特别敏感的人群以外,对公众没有危害!",
      "alarm": {
        "alarm_type": "",
        "alarm_level": "",
        "alarm_content": ""
      },
      "tem1": "16℃",
      "tem2": "9℃",
      "tem": "16℃",
      "win": [
        "无持续风向",
        "无持续风向"
      ],
      "win_speed": "<3级",
      "hours": [
        {
          "day": "11日08时",
          "wea": "阴",
          "tem": "10℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "11日11时",
          "wea": "多云",
          "tem": "14℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "11日14时",
          "wea": "多云",
          "tem": "16℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "11日17时",
          "wea": "多云",
          "tem": "13℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "11日20时",
          "wea": "多云",
          "tem": "13℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "11日23时",
          "wea": "多云",
          "tem": "9℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "12日02时",
          "wea": "多云",
          "tem": "11℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "12日05时",
          "wea": "多云",
          "tem": "12℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        }
      ],
      "index": [
        {
          "title": "紫外线指数",
          "level": "弱",
          "desc": "辐射较弱,涂擦SPF12-15、PA+护肤品。"
        },
        {
          "title": "</em><em>",
          "level": null,
          "desc": "春天不减肥,夏天徒伤悲。天气较舒适,快去运动吧。"
        },
        {
          "title": "健臻·血糖指数",
          "level": "较易波动",
          "desc": "血糖较易波动,注意监测。"
        },
        {
          "title": "穿衣指数",
          "level": "较冷",
          "desc": "建议着厚外套加毛衣等服装。"
        },
        {
          "title": "洗车指数",
          "level": "较适宜",
          "desc": "无雨且风力较小,易保持清洁度。"
        },
        {
          "title": "空气污染扩散指数",
          "level": "中",
          "desc": "易感人群应适当减少室外活动。"
        }
      ]
    },
    {
      "day": "12日(明天)",
      "date": "2019-04-12",
      "week": "星期五",
      "wea": "多云",
      "wea_img": "yun",
      "tem1": "17℃",
      "tem2": "9℃",
      "tem": "12℃",
      "win": [
        "无持续风向",
        "无持续风向"
      ],
      "win_speed": "<3级",
      "hours": [
        {
          "day": "12日08时",
          "wea": "多云",
          "tem": "12℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "12日11时",
          "wea": "多云",
          "tem": "14℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "12日14时",
          "wea": "多云",
          "tem": "15℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "12日17时",
          "wea": "多云",
          "tem": "17℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "12日20时",
          "wea": "多云",
          "tem": "15℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "12日23时",
          "wea": "多云",
          "tem": "11℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "13日02时",
          "wea": "多云",
          "tem": "11℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "13日05时",
          "wea": "多云",
          "tem": "11℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        }
      ],
      "index": [
        {
          "title": "紫外线指数",
          "level": "弱",
          "desc": "辐射较弱,涂擦SPF12-15、PA+护肤品。"
        },
        {
          "title": "</em><em>",
          "level": null,
          "desc": "春天不减肥,夏天徒伤悲。天气较舒适,快去运动吧。"
        },
        {
          "title": "健臻·血糖指数",
          "level": "较易波动",
          "desc": "血糖较易波动,注意监测。"
        },
        {
          "title": "穿衣指数",
          "level": "较冷",
          "desc": "建议着厚外套加毛衣等服装。"
        },
        {
          "title": "洗车指数",
          "level": "较适宜",
          "desc": "无雨且风力较小,易保持清洁度。"
        },
        {
          "title": "空气污染扩散指数",
          "level": "中",
          "desc": "易感人群应适当减少室外活动。"
        }
      ]
    },
    {
      "day": "13日(后天)",
      "date": "2019-04-13",
      "week": "星期六",
      "wea": "晴",
      "wea_img": "qing",
      "tem1": "20℃",
      "tem2": "9℃",
      "tem": "9℃",
      "win": [
        "无持续风向",
        "无持续风向"
      ],
      "win_speed": "<3级",
      "hours": [
        {
          "day": "13日08时",
          "wea": "多云",
          "tem": "9℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "13日11时",
          "wea": "晴",
          "tem": "16℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "13日14时",
          "wea": "晴",
          "tem": "20℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "13日17时",
          "wea": "晴",
          "tem": "19℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "13日20时",
          "wea": "晴",
          "tem": "16℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "13日23时",
          "wea": "晴",
          "tem": "14℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "14日02时",
          "wea": "晴",
          "tem": "14℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "14日05时",
          "wea": "晴",
          "tem": "9℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        }
      ],
      "index": [
        {
          "title": "紫外线指数",
          "level": "中等",
          "desc": "涂擦SPF大于15、PA+防晒护肤品。"
        },
        {
          "title": "减肥指数",
          "level": null,
          "desc": "天气较舒适,减肥正当时。"
        },
        {
          "title": "健臻·血糖指数",
          "level": "较易波动",
          "desc": "血糖较易波动,注意监测。"
        },
        {
          "title": "穿衣指数",
          "level": "较舒适",
          "desc": "建议穿薄外套或牛仔裤等服装。"
        },
        {
          "title": "洗车指数",
          "level": "较适宜",
          "desc": "无雨且风力较小,易保持清洁度。"
        },
        {
          "title": "空气污染扩散指数",
          "level": "中",
          "desc": "易感人群应适当减少室外活动。"
        }
      ]
    },
    {
      "day": "14日(周日)",
      "date": "2019-04-14",
      "week": "星期日",
      "wea": "多云转晴",
      "wea_img": "yun",
      "tem1": "18℃",
      "tem2": "8℃",
      "tem": "9℃",
      "win": [
        "无持续风向",
        "无持续风向"
      ],
      "win_speed": "<3级",
      "hours": [
        {
          "day": "14日08时",
          "wea": "晴",
          "tem": "9℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "14日14时",
          "wea": "多云",
          "tem": "14℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "14日20时",
          "wea": "多云",
          "tem": "14℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "15日02时",
          "wea": "晴",
          "tem": "9℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        }
      ],
      "index": [
        {
          "title": "紫外线指数",
          "level": "弱",
          "desc": "辐射较弱,涂擦SPF12-15、PA+护肤品。"
        },
        {
          "title": "减肥指数",
          "level": null,
          "desc": "春天不减肥,夏天徒伤悲。天气较舒适,快去运动吧。"
        },
        {
          "title": "健臻·血糖指数",
          "level": "较易波动",
          "desc": "血糖较易波动,注意监测。"
        },
        {
          "title": "穿衣指数",
          "level": "较冷",
          "desc": "建议着厚外套加毛衣等服装。"
        },
        {
          "title": "洗车指数",
          "level": "较适宜",
          "desc": "无雨且风力较小,易保持清洁度。"
        },
        {
          "title": "空气污染扩散指数",
          "level": "中",
          "desc": "易感人群应适当减少室外活动。"
        }
      ]
    },
    {
      "day": "15日(周一)",
      "date": "2019-04-15",
      "week": "星期一",
      "wea": "晴转多云",
      "wea_img": "yun",
      "tem1": "21℃",
      "tem2": "10℃",
      "tem": "9℃",
      "win": [
        "无持续风向",
        "无持续风向"
      ],
      "win_speed": "<3级",
      "hours": [
        {
          "day": "15日08时",
          "wea": "晴",
          "tem": "9℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "15日14时",
          "wea": "晴",
          "tem": "20℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "15日20时",
          "wea": "晴",
          "tem": "17℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "16日02时",
          "wea": "多云",
          "tem": "13℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        }
      ],
      "index": [
        {
          "title": "紫外线指数",
          "level": "中等",
          "desc": "涂擦SPF大于15、PA+防晒护肤品。"
        },
        {
          "title": "减肥指数",
          "level": null,
          "desc": "天气较舒适,减肥正当时。"
        },
        {
          "title": "健臻·血糖指数",
          "level": "较易波动",
          "desc": "血糖较易波动,注意监测。"
        },
        {
          "title": "穿衣指数",
          "level": "较舒适",
          "desc": "建议穿薄外套或牛仔裤等服装。"
        },
        {
          "title": "洗车指数",
          "level": "较适宜",
          "desc": "无雨且风力较小,易保持清洁度。"
        },
        {
          "title": "空气污染扩散指数",
          "level": "中",
          "desc": "易感人群应适当减少室外活动。"
        }
      ]
    },
    {
      "day": "16日(周二)",
      "date": "2019-04-16",
      "week": "星期二",
      "wea": "多云",
      "wea_img": "yun",
      "tem1": "19℃",
      "tem2": "7℃",
      "tem": "10℃",
      "win": [
        "无持续风向",
        "无持续风向"
      ],
      "win_speed": "<3级",
      "hours": [
        {
          "day": "16日08时",
          "wea": "多云",
          "tem": "10℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "16日14时",
          "wea": "多云",
          "tem": "18℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "16日20时",
          "wea": "多云",
          "tem": "15℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "17日02时",
          "wea": "多云",
          "tem": "13℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        }
      ],
      "index": [
        {
          "title": "紫外线指数",
          "level": "弱",
          "desc": "辐射较弱,涂擦SPF12-15、PA+护肤品。"
        },
        {
          "title": "减肥指数",
          "level": null,
          "desc": "天气较舒适,减肥正当时。"
        },
        {
          "title": "健臻·血糖指数",
          "level": "较易波动",
          "desc": "血糖较易波动,注意监测。"
        },
        {
          "title": "穿衣指数",
          "level": "较舒适",
          "desc": "建议穿薄外套或牛仔裤等服装。"
        },
        {
          "title": "洗车指数",
          "level": "较适宜",
          "desc": "无雨且风力较小,易保持清洁度。"
        },
        {
          "title": "空气污染扩散指数",
          "level": "中",
          "desc": "易感人群应适当减少室外活动。"
        }
      ]
    },
    {
      "day": "17日(周三)",
      "date": "2019-04-17",
      "week": "星期三",
      "wea": "多云",
      "wea_img": "yun",
      "tem1": "19℃",
      "tem2": "7℃",
      "tem": "7℃",
      "win": [
        "无持续风向",
        "无持续风向"
      ],
      "win_speed": "<3级",
      "hours": [
        {
          "day": "17日08时",
          "wea": "多云",
          "tem": "7℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "17日14时",
          "wea": "多云",
          "tem": "18℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "17日20时",
          "wea": "多云",
          "tem": "14℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        },
        {
          "day": "18日02时",
          "wea": "多云",
          "tem": "8℃",
          "win": "无持续风向",
          "win_speed": "<3级"
        }
      ],
      "index": [
        {
          "title": "紫外线指数",
          "level": "弱",
          "desc": "辐射较弱,涂擦SPF12-15、PA+护肤品。"
        },
        {
          "title": "减肥指数",
          "level": null,
          "desc": "天气较舒适,减肥正当时。"
        },
        {
          "title": "健臻·血糖指数",
          "level": "较易波动",
          "desc": "血糖较易波动,注意监测。"
        },
        {
          "title": "穿衣指数",
          "level": "较舒适",
          "desc": "建议穿薄外套或牛仔裤等服装。"
        },
        {
          "title": "洗车指数",
          "level": "较适宜",
          "desc": "无雨且风力较小,易保持清洁度。"
        },
        {
          "title": "空气污染扩散指数",
          "level": "中",
          "desc": "易感人群应适当减少室外活动。"
        }
      ]
    }
  ]
}

​ 将其保存为utf-8的文本文件,并将后缀名修改为json,用Firfox打开,可以看到json文件的具体信息:

可以看到,实现是普通的字典对:{”city”:”乌鲁木齐”},然后是data对应的数组。

Json解析方法如下:1555078964052

  1. 首先使用QFile::readAll()读取Json数据

  2. 使用QJsonDocment::fromjson()得到QJsonDocment对象

#include <QCoreApplication>
#include <QString>
#include <QFile>
#include <QDebug>
#include <QByteArray>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonParseError>
int main(int argc,char *argv[]){
    QCoreApplication a(argc, argv);
// 打开Json文件
    QFile file("E:\\Project\\Qt\\QJson\\w.json");
    file.open(QIODevice::ReadOnly);
//创建QJsonDocment对象
    QJsonParseError json_error;
    QJsonDocument json_doc=QJsonDocument::fromJson(file.readAll(),&json_error);
    if(json_error.error!=QJsonParseError::NoError)
        qDebug()<<json_error.error;
// 其他解析Json的数据
}

​ 上面代码是解析Json的基本代码。在继续写解析Json的代码之前,先看几个必须了解的类方法和类属性:

常用的类方法

QJsonDocment类用于读取或写入Json对象:

| 方法 | 用途 | | :———————————————————-: | :————————————–: | | bool isArray() const | 若Json对象为array,返回true | | const QJsonValue operator[](const QString &key) const | 重载函数,用于访问键值 | | QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = nullptr) | 静态函数,用于从QByteArray中读取Json文档 |

QJsonObject类代表了一个Json对象,其用于解析Json的主要方法为:

| 方法 | 用途 | | :———————————————-: | :——————–: | | QStringList keys()const | 用于列出所有Json的键 | | QJsonValue value(const QString &key) const | 重载方法,用于访问键值 | | QJsonValue operator[](const QString &key) const | 重载方法,用于访问键值 |

QJsonValue类代表了Json对象的值,在QJsonDocmentQJsonObject之间起着桥梁的作用:

| 方法 | 用途 | | :—————————————————-: | :———————————–: | | QJsonArray toArray() const | 用于将QJsonValue转换为QJsonArray对象 | | QJsonObject toObject() const | 用于将QJsonValue转换为QJsonObject对象 | | QString toString() const | 用于将QJsonValue转换为QString对象 | | QJsonValue::Type type() const | 用于获取QJsonValue对象实际代表的类型 | | const QJsonValue operator[](const QString &key) const | 用于获取Json对应的键值 |

读取一级键值

​ 读取一级键值很简单,直接对QJsonDocment对象进行下标索引即可:

qDebug()<<json_doc["city"].toString();

输出结果:

“乌鲁木齐”

读取一级数组

​ 在上面写出的Json中,data代表了Json数据的一个数组,用于储存乌鲁木齐市七天的天气状况:

1555078226990

​ 要读取数组,实现对QJsonDocment进行下标索引,获得data键对应的QJsonValue,其实际代表一个Array,因此,将其使用toArray()方法得到实际的类型,再对每一个Array项先转换为QJsonObject,然后进行索引,并转换为QString

QJsonValue jsonVal=json_doc["data"];
QJsonArray jsonArr=jsonVal.toArray();//得到数组对象
foreach(QJsonValue x,jsonArr){// 对数组对象进行迭代
    qDebug()<<"读取二级键值[\"day\"]"<<x.toObject().value("day").toString();//获取数组day对应的键值
}

输出结果:

读取二级键值[”day”] “11日(今天)” 读取二级键值[”day”] “12日(明天)” 读取二级键值[”day”] “13日(后天)” 读取二级键值[”day”] “14日(周日)” 读取二级键值[”day”] “15日(周一)” 读取二级键值[”day”] “16日(周二)” 读取二级键值[”day”] “17日(周三)”

读取三级键值

​ 上面的Json数据中,以index数组为例,数据嵌套的关系为:

​ $Json数据\leftarrow data数组\leftarrow index数组$

下面读取嵌套在data数组中的index数组

1555078306800

​ 思路和上面一样,实现将jsonArr对象进行索引,再通过QJsonObject为中介,得到index代表的数组:

QJsonArray jsonArr2=jsonArr[0].toObject()["index"].toArray();//得到index数组对应的对象
foreach(QJsonValue x,jsonArr2){
    qDebug()<<x["level"].toString();//打印数组的level键值
}

输出结果为:

二级数组: “弱” 二级数组: “” 二级数组: “较易波动” 二级数组: “较冷” 二级数组: “较适宜” 二级数组: “中”

读取数组的全部代码

#include <QCoreApplication>
#include <QJsonArray>
#include <QString>
#include <QFile>
#include <QDebug>
#include <QByteArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonParseError>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
// 打开Json文件
    QFile file("E:\\Project\\Qt\\QJson\\w.json");
    file.open(QIODevice::ReadOnly);
//创建QJsonDoc对象
    QJsonParseError json_error;
    QJsonDocument json_doc=QJsonDocument::fromJson(file.readAll(),&json_error);
    if(json_error.error!=QJsonParseError::NoError)
        qDebug()<<json_error.error;
// 读取Json数据
    qDebug()<<"读取一级键值[\"city\"]:"<<json_doc["city"].toString();
// 读取一级数组
    QJsonValue jsonVal=json_doc["data"];
    QJsonArray jsonArr=jsonVal.toArray();
    foreach(QJsonValue x,jsonArr){
        qDebug()<<"读取二级键值[\"day\"]"<<x.toObject().value("day").toString();
    }
// 读取二级数组
    QJsonArray jsonArr2=jsonArr[0].toObject()["index"].toArray();
    foreach(QJsonValue x,jsonArr2){
        qDebug()<<"二级数组:"<<x["level"].toString();
    }
    return a.exec();
}

输出结果为:

读取一级键值[”city”]: “乌鲁木齐” 读取二级键值[”day”] “11日(今天)” 读取二级键值[”day”] “12日(明天)” 读取二级键值[”day”] “13日(后天)” 读取二级键值[”day”] “14日(周日)” 读取二级键值[”day”] “15日(周一)” 读取二级键值[”day”] “16日(周二)” 读取二级键值[”day”] “17日(周三)” 二级数组: “弱” 二级数组: “” 二级数组: “较易波动” 二级数组: “较冷” 二级数组: “较适宜” 二级数组: “中”

​ 对于其他级别的嵌套数组,也就是不断的转换对象了。

一个特殊的QJsonObject对象

实现观察高亮部分:

1555078964052

firefox对Json的数组进行了编号,直观体现就是data数组和index数组的项上级都有0,1,2,3这样的标号。但是高亮部分对应的alarm项却没有进行编号,可以认为,alarm不是一个数组

实现查看alarm的实际类型:

qDebug()<<jsonArr[0].toObject().value("alarm").type()

输出结果为:

5

查看type()对应的文档,可以看到type()返回一个QJsonValue的枚举值,5代表的是QJsonObject

既然alarm代表的是一个QJsonObject对象,那么获取键值直接对其进行索引即可:

qDebug()<<qDebug()<<jsonArr[0].toObject().value("alarm").toObject()["alarm_content"];
// 这里不再toString(),因为这个键值为空

输出结果为:

QJsonValue(string, “”)