在使用qt进行开发时,或者其它语言开发时,json数据格式是我们绕不过去的一个环节:
eg:服务器进行数据交互,保存用户配置信息等等,当然格式有多种:ini;xml,这里说下json;
json解析首先分为这几个类: QJsonDocument QJsonObject QJsonArray QJsonValue
QJsonParseError;
一般分为组织数据给别人使用或者解析整包里面的内容;
这里举个例子,linux系统获取根分区所在的最上层的分区名称,先贴段代码;
#ifndef JSON_CONSTANTS_H
#define JSON_CONSTANTS_H
#include <QString>
typedef struct {
bool isFindRoot = false;
QString parentRootPart;
} PartInfo;
#endif
#include "widget.h"
#include "json.h"
#include <QApplication>
#include <QDebug>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QFile file("/home/zhanglei/Desktop/diskinfo.txt");
if (!file.open(QIODevice::ReadOnly)) {
qInfo() << "open file failed!" << file.errorString();
return 1;
}
QByteArray data = file.readAll();
DeviceInfo deviceInfo;
deviceInfo.parseJsonData(data);
qInfo() << endl << endl << deviceInfo.getParentRootPartName();
return app.exec();
}
#ifndef JSON_H
#define JSON_H
#include "jsonconstants.h"
#include <QObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
class DeviceInfo : public QObject
{
Q_OBJECT
public:
DeviceInfo(QObject *parent = Q_NULLPTR);
~DeviceInfo();
QJsonObject parseJsonData(const QByteArray &data);
QStringList getParentRootPartName();
private:
QJsonObject getJsonFromByteArray(const QByteArray &byteArray);
void parseChildData(const QJsonArray &jsonArray, bool isMark, PartInfo &partInfo);
QStringList partName;
};
#endif
#include "json.h"
#include <QDebug>
DeviceInfo::DeviceInfo(QObject *parent)
: QObject (parent)
{
}
DeviceInfo::~DeviceInfo()
{
}
QJsonObject DeviceInfo::parseJsonData(const QByteArray &data)
{
if (data.isEmpty())
return QJsonObject();
QJsonObject objectData = getJsonFromByteArray(data);
QJsonArray jsonArray = objectData.value("blockdevices").toArray();
if(jsonArray.size() > 0){
for(int i = 0; i < jsonArray.size(); i++) {
QJsonObject object = jsonArray.at(i).toObject();
qInfo() << i;
qInfo() << "hotplug: " << object.value("hotplug").toBool();
qInfo() << "model: " << object.value("model").toString();
qInfo() << "mountpoint: " << object.value("mountpoint").toString();
qInfo() << "name: " << object.value("name").toString();
qInfo() << "serial: " << object.value("serial").toString();
qInfo() << "type: " << object.value("type").toString();
qInfo() << "vendor: " << object.value("vendor").toString();
PartInfo partInfos;
parseChildData(object.value("children").toArray(), true, partInfos);
if (partInfos.isFindRoot)
partName <<partInfos.parentRootPart;
qInfo() << endl;
}
}
return objectData;
}
QStringList DeviceInfo::getParentRootPartName()
{
return partName;
}
QJsonObject DeviceInfo::getJsonFromByteArray(const QByteArray &byteArray)
{
QJsonParseError jsonParseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(byteArray, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qInfo() << "json parse error: " << jsonParseError.errorString();
return QJsonObject();
}
QJsonObject jsonObj = jsonDoc.object();
return jsonObj;
}
void DeviceInfo::parseChildData(const QJsonArray &jsonArray, bool isMark, PartInfo &partInfo)
{
if(jsonArray.size() > 0){
for(int i = 0; i < jsonArray.size(); i++) {
QJsonObject object = jsonArray.at(i).toObject();
if(isMark && !partInfo.isFindRoot) {
qInfo () << "parent boot part name is :" << object.value("name").toString();
partInfo.parentRootPart = object.value("name").toString();
}
qInfo() << "****child**** : " << i;
qInfo() << "hotplug: " << object.value("hotplug").toBool();
qInfo() << "model: " << object.value("model").toString();
qInfo() << "mountpoint: " << object.value("mountpoint").toString();
qInfo() << "name: " << object.value("name").toString();
qInfo() << "serial: " << object.value("serial").toString();
qInfo() << "type: " << object.value("type").toString();
qInfo() << "vendor: " << object.value("vendor").toString();
if ((object.value("mountpoint").toString() == "/") && (object.value("type").toString() == "part"))
partInfo.isFindRoot = true;
parseChildData(object.value("children").toArray(), false, partInfo);
}
}
}
所需解析的json内容为:
{
"blockdevices": [
{"name":"sda", "serial":"WD-WCC6Y5PXXUJX", "type":"disk", "model":"WDC_WD10EZEX-08WN4A0", "mountpoint":null, "vendor":"ATA ", "hotplug":false,
"children": [
{"name":"sda1", "serial":null, "type":"part", "model":null, "mountpoint":"/", "vendor":null, "hotplug":false}
]
},
{"name":"nvme0n1", "serial":"K15352J001489", "type":"disk", "model":"FORESEE P900F256GBH", "mountpoint":null, "vendor":null, "hotplug":false,
"children": [
{"name":"nvme0n1p1", "serial":null, "type":"part", "model":null, "mountpoint":"/boot/efi", "vendor":null, "hotplug":false},
{"name":"nvme0n1p2", "serial":null, "type":"part", "model":null, "mountpoint":"/boot", "vendor":null, "hotplug":false},
{"name":"nvme0n1p3", "serial":null, "type":"part", "model":null, "mountpoint":"null", "vendor":null, "hotplug":false,
"children":[
{"name":"nvme0n1p31", "serial":null, "type":"part", "model":null, "mountpoint":"null", "vendor":null, "hotplug":false,
"children":[
{"name":"nvme0n1p32", "serial":null, "type":"part", "model":null, "mountpoint":"/", "vendor":null, "hotplug":false}]
}
]
},
{"name":"nvme0n1p4", "serial":null, "type":"part", "model":null, "mountpoint":null, "vendor":null, "hotplug":false},
{"name":"nvme0n1p5", "serial":null, "type":"part", "model":null, "mountpoint":"/recovery", "vendor":null, "hotplug":false},
{"name":"nvme0n1p6", "serial":null, "type":"part", "model":null, "mountpoint":"[SWAP]", "vendor":null, "hotplug":false}
]
}
]
}
结果为:
这里遍历children可以使用递归,这里记录下,递归时一定要确定好自己的退出条件,一旦陷入死循环,你懂的,程序直接就crash了,直接就爽歪歪了;