[Qt5] QJson库进行存储、加载数据
目录:
- 一. Boost库介绍
- 二. QJson库介绍
- 三. QJson库生成与解析结构体数据
- 四. QJson库读、存数据的完整代码操作
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目视频教程+代码,C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓
一. Boost库介绍
利用Boost库对视觉任务参数的存读时,有一个缺陷就是如果UI界面新增参数时,在界面初始化的时候会读取不到这个新增的参数,导致原任务设置好的的参数会被清掉进而变成默认参数,需要重新做任务保存参数。这对项目初期开发阶段而言非常不友好,增大调试时间成本。
一般需要增加版本号来解决上述的问题:
namespace boost
{
namespace serialization
{
template<typename Archive>
void serialize(Archive & ar, MS_CreateModelSingle_Params & d, const unsigned int version)
{
//VISION_LOG_INFO("%d", version);查看版本号
ar & BOOST_SERIALIZATION_NVP(d.m_isPreventReverse);//是否启用防反
ar & BOOST_SERIALIZATION_NVP(d.m_threshLow); //阈值下限
ar & BOOST_SERIALIZATION_NVP(d.m_threshHigh); //阈值上限
ar & BOOST_SERIALIZATION_NVP(d.m_area); //面积
if(version == 2) //只有 version = 新版本号才读取新参数
{
ar & BOOST_SERIALIZATION_NVP(d.m_areaRatio); //面积占比
}
}
}
}
BOOST_CLASS_VERSION(MS_CreateModelSingle_Params, 2);//当前新版本号,重新保存任务版本号将会更新
这样的话,在初始化的时候就不会读取到新增的参数,也就不会崩溃了。只有在重新保存参数的时候,才会将新增的参数保存到任务文件中。
二. QJson库介绍
本文使用QJson库来作为参数的保存与读取,不使用版本信息也可解决上述Boost库存在的缺陷。
JSON(JavaScript对象表示法)是一种轻量级的数据交换格式。它可以表示整数,实数,字符串,值的有序序列以及名称/值对的集合。
关于Qt中对JSON的生成与解析,Qt5以前的版本,可以使用QJson库,需要单独下载、编译,才能使用。到了 Qt5,提供了专门的QJsonDocument及其相关类来读和写JSON文档。
Json类
介绍
QJsonDoucument
它封装了一个完整的 JSON 文档,并且可以从 UTF-8 编码的基于文本的表示以及 Qt 自己的二进制格式读取和写入该文档
QJsonArray
JSON 数组是一个值列表。可以通过从数组中插入和删除 QJsonValue 来操作该列表
QJsonObject
JSON 对象是键值对的列表,其中键是唯一的字符串,值由 QJsonValue 表示
QJsonValue
该类封装了 JSON 支持的数据类型
三. QJson库生成与解析结构体数据
安装环境:本文使用的Qt版本—Qt5.12.10
1、包含头文件:
struct MS_EdgeLineFitParam
{
//初始化结构体内数据
MS_EdgeLineFitParam()
{
m_isAssignCenterEdge = false;
m_measureWidth = 5;
m_measureHeight = 0.0;
}
bool m_isAssignCenterEdge;
int m_measureWidth;
double m_measureHeight;
//将结构体中的数据序列化成本地`Json`数据
QJsonValue toJson()
{
// 定义 { } 对象
QJsonObject jObj;
// 插入元素,对应键值对
jObj.insert("m_isAssignCenterEdge", m_isAssignCenterEdge);
jObj.insert("m_measureWidth", m_measureWidth);
jObj.insert("m_measureHeight", m_measureHeight);
return QJsonValue(jObj);
}
};
3、将本地Json数据进行反序列化成结构体中的数据(fromJson — 解析数据),
struct MS_EdgeLineFitParam
{
//初始化结构体内数据
MS_EdgeLineFitParam()
{
m_isAssignCenterEdge= false;
m_measureWidth= 5;
m_dMeasureHeight = 0.0;
}
bool m_isAssignCenterEdge;
int m_measureWidth;
double m_measureHeight;
//将本地`Json`数据进行反序列化成结构体中的数据
static MS_EdgeLineFitParam fromJson(QJsonValue _json)
{
MS_EdgeLineFitParam task;
//定义空对象
QJsonObject jObj = _json.toObject();
//将Json类型数据进行反序列化
task.m_isAssignCenterEdge= jObj.value("m_isAssignCenterEdge").toBool();
task.m_measureWidth= jObj.value("m_measureWidth").toInt();
task.m_measureHeight= jObj.value("m_measureHeight").toDouble();
return task;
}
};
四. QJson库读、存数据的完整代码操作
1、结构体数据类型的序列化与反序列化
enum ME_EdgeLineFitShape
{
EDGELINE_LINE = 0,
};
struct MS_IntersectionParam
{
MS_IntersectionParam()
{
m_intersectionEdgeOne = 0;
}
int m_intersectionEdgeOne;
static MS_IntersectionParam fromJson(QJsonValue _json)
{
MS_IntersectionParam task;
QJsonObject jObj = _json.toObject();
task.m_intersectionEdgeOne = jObj.value("m_intersectionEdgeOne").toInt();
return task;
}
QJsonValue toJson()
{
QJsonObject jObj;
jObj.insert("m_intersectionEdgeOne", m_intersectionEdgeOne);
return QJsonValue(jObj);
}
};
struct MS_EdgeLineFitParam
{
//初始化结构体内数据
MS_EdgeLineFitParam()
{
m_isAssignCenterEdge= false;
m_measureWidth= 5;
m_dMeasureHeight = 0.0;
}
bool m_isAssignCenterEdge;
int m_measureWidth;
double m_measureHeight;
ME_EdgeLineFitShape m_edgeLineFitShape; //自定义的枚举 ME_EdgeLineFitShape
MS_IntersectionParam m_intersectionParam; //自定义的结构体 MS_IntersectionParam
static MS_EdgeLineFitParam fromJson(QJsonValue _json)
{
MS_EdgeLineFitParam task;
QJsonObject jObj = _json.toObject();
task.m_isAssignCenterEdge = jObj.value("m_isAssignCenterEdge").toBool();
task.m_measureWidth = jObj.value("m_measureWidth").toInt();
task.m_measureHeight = jObj.value("m_measureHeight").toDouble();
//fromJson中自定义的枚举的写法
task.m_edgeLineFitShape = (ME_EdgeLineFitShape)jObj.value("m_edgeLineFitShape").toInt();
//fromJson中自定义结构体的写法
task.m_intersectionParam = MS_IntersectionParam::fromJson(jObj.value("m_intersectionParam"));
return task;
}
QJsonValue toJson()
{
QJsonObject jObj;
jObj.insert("m_isAssignCenterEdge", m_isAssignCenterEdge);
jObj.insert("m_measureWidth", m_measureWidth);
jObj.insert("m_measureHeight", m_measureHeight);
//toJson中自定义的枚举的写法和常规写法一致
jObj.insert("m_edgeLineFitShape", m_edgeLineFitShape);
//toJson中自定义结构体的写法
jObj.insert("m_intersectionParam", m_intersectionParam.toJson());
return QJsonValue(jObj);
}
};
struct VISIONLIBRARY_API MS_EdgeLineFit
{
//输出结构体包含的数据类型map,bool
std::map<int, MS_EdgeLineFitParam> m_edgeLineFitParam;
bool m_isAffineContour = true;
//解析、读取保存到的本地数据
static MS_EdgeLineFit fromJson(QJsonValue _json)
{
MS_EdgeLineFit task;
QJsonObject jObj = _json.toObject();
task.m_name = QString(jObj.value("m_name").toString().toLocal8Bit());
//fromJson中自定义map的写法
QJsonArray edgeLineFitParam = jObj.value("m_edgeLineFitParam").toArray();
for (auto value : edgeLineFitParam)
{
QJsonArray jArr = value.toArray();
int num = jArr[0].toInt();
MS_EdgeLineFitParam fitParam = MS_EdgeLineFitParam::fromJson(jArr[1]);
task.m_edgeLineFitParam.insert(std::map<int, MS_EdgeLineFitParam>::value_type(num, fitParam));
}
task.m_isAffineContour = jObj.value("m_isAffineContour").toBool();
return task;
}
//结构体数据通过toJson转换保存本地
QJsonValue toJson()
{
QJsonObject jObj;
jObj.insert("task_name", m_name);
std::map<int, MS_EdgeLineFitParam>::iterator fitParamIter;
QJsonArray fitParamJArr;
for (fitParamIter = m_edgeLineFitParam.begin(); fitParamIter != m_edgeLineFitParam.end(); fitParamIter++)
{
QJsonArray jArr;
jArr.append(fitParamIter->first);
jArr.append(fitParamIter->second.toJson());
fitParamJArr.append(jArr);
}
jObj.insert("m_edgeLineFitParam", fitParamJArr);
jObj.insert("m_isAffineContour", m_isAffineContour);
return QJsonValue(jObj);
}
};
Q_DECLARE_METATYPE(MS_EdgeLineFit)
2、读、存QJson生成的.json文件
MS_EdgeLineFit::MS_EdgeLineFit(const QString& _name)
{
m_name = _name;
m_edgeLineFitPath = "./VisionFiles/EdgeLineFit/" + m_name + "/";
read();
}
bool MS_EdgeLineFit::read()
{
QDir traDir(m_edgeLineFitPath);
if (!traDir.exists()) {
ERROR_VISION("read attachData faild due to no such directory!");
return true;
}
QString fileName = QString(m_edgeLineFitPath + "attachData.json").toStdString().c_str();
INFO_VISION("read attachData taskPath, %s", fileName.toStdString().c_str());
QFileInfo cfg_json(fileName);
if (!cfg_json.exists())
{
INFO_VISION("read attachData faild due to no such file!");
return false;
}
QFile file_json(fileName);
if (!(file_json.open(QIODevice::ReadOnly | QIODevice::Text)))
{
INFO_VISION("read attachData faild due to file cannot be opened!");
return false;
}
QByteArray cfgContent = file_json.readAll();
file_json.close();
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(cfgContent, &jsonError);
if (!jsonDoc.isNull() && (jsonError.error == QJsonParseError::NoError) && jsonDoc.isObject())
{
INFO_VISION("read attachData success, %s", fileName.toStdString().c_str());
QJsonObject jObj = jsonDoc.object();
MS_EdgeLineFit task = MS_EdgeLineFit::fromJson(jObj.value("Task"));
m_edgeLineFitParam = task.m_edgeLineFitParam;
m_isAffineContour = task.m_isAffineContour;
return true;
}
else
{
INFO_VISION("read attachData faild due to attachData exception!");
return false;
}
}
bool MS_EdgeLineFit::write()
{
writeGraphic();
QString fileName = QString(m_edgeLineFitPath + "attachData.json").toStdString().c_str();
INFO_VISION("write attachData taskPath, %s", fileName.toStdString().c_str());
QJsonDocument doc;
QJsonObject jObj;
MS_EdgeLineFit task(m_name);
task.m_edgeFitHRegion = m_edgeFitHRegion;
task.m_isAffineContour = m_isAffineContour;
jObj.insert("Task", task.toJson());
doc.setObject(jObj);
QString jsonText = doc.toJson();
QFile cfgFile(fileName);
if (!(cfgFile.open(QIODevice::WriteOnly | QIODevice::Text)))
{
ERROR_VISION("Error occured in write attachData fail due to file cannot be opened!");
return false;
}
cfgFile.write(jsonText.toStdString().data());
cfgFile.close();
return true;
}
五. 总结
本文主要对结构体中数据类型使用QJson库的方式进行读存,数据类型包括bool、int、double、enum、map等,以及结构体内嵌套子结构体情况下的处理。
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目视频教程+代码,C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓