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解析方法如下:
首先使用QFile::readAll()读取Json数据
使用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对象的值,在QJsonDocment和QJsonObject之间起着桥梁的作用:
| 方法 | 用途 | | :—————————————————-: | :———————————–: | | 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数据的一个数组,用于储存乌鲁木齐市七天的天气状况:

要读取数组,实现对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数组:

思路和上面一样,实现将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对象
实现观察高亮部分:

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, “”)