[Qt5] QJson库进行存储、加载数据

简介: [Qt5] QJson库进行存储、加载数据

一. 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、包含头文件:

#include <QJsonDocument>

2、将结构体中的数据序列化成本地Json数据(toJson — 生成数据),

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库的方式进行读存,数据类型包括boolintdoubleenummap等,以及结构体内嵌套子结构体情况下的处理。


下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。


目录
相关文章
|
25天前
|
编解码
qt中使用dll库的方法
qt中使用dll库的方法
15 2
|
25天前
|
存储
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
|
1月前
|
算法 API C++
Qt框架与STL库之间的巅峰对决:差异、优缺点及适用场景
Qt框架与STL库之间的巅峰对决:差异、优缺点及适用场景
129 0
|
1月前
|
Linux Windows
imx6ull开发板之qt应用编程读取AP3216c(光照,距离)数据。
imx6ull开发板之qt应用编程读取AP3216c(光照,距离)数据。
20 0
|
2月前
|
存储 自然语言处理
QT案例词典 -- 存储内容及遍历
QT案例词典 -- 存储内容及遍历
12 1
|
3月前
|
JSON JavaScript 前端开发
C++ Qt开发:运用QJSON模块解析数据
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用`QJson`组件的实现对JSON文本的灵活解析功能。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它易于人阅读和编写,也易于机器解析和生成。该格式是基于JavaScript语言的一个子集,但它是一种独立于语言的数据格式,因此可以在许多不同的编程语言中使用。
34 0
C++ Qt开发:运用QJSON模块解析数据
|
4月前
|
算法 编译器
[C++&Qt] 通过信号与槽传递数据
[C++&Qt] 通过信号与槽传递数据
52 0
|
1月前
|
网络协议 C++
C++ Qt开发:QTcpSocket网络通信组件
`QTcpSocket`和`QTcpServer`是Qt中用于实现基于TCP(Transmission Control Protocol)通信的两个关键类。TCP是一种面向连接的协议,它提供可靠的、双向的、面向字节流的通信。这两个类允许Qt应用程序在网络上建立客户端和服务器之间的连接。Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用`QTcpSocket`组件实现基于TCP的网络通信功能。
38 8
C++ Qt开发:QTcpSocket网络通信组件
|
1天前
|
开发框架 数据可视化 编译器
Qt的魅力:探索跨平台图形界面开发之旅
Qt的魅力:探索跨平台图形界面开发之旅
8 1
|
17天前
|
图形学 Python 容器
【PyQt5桌面应用开发】3.Qt Designer快速入门(控件详解)
【PyQt5桌面应用开发】3.Qt Designer快速入门(控件详解)
35 0

热门文章

最新文章

推荐镜像

更多