Json在Qt中的使用

news2024/12/30 2:04:30

文章目录

  • Json在Qt中的使用
    • 主要使用的类
    • QJsonValue
    • QJsonObject
    • QJsonDocument
    • 实战
      • 1. 手动写Json文件
      • 2. 实现程序(从Json文件中读取数据,更改Json文件中的数据)

Json在Qt中的使用

主要使用的类

Json 类介绍
QJsonDocument它封装了一个完整的 JSON 文档,并且可以从 UTF-8 编码的基于文本的表示以及 Qt 自己的二进制格式读取和写入该文档。
QJsonArrayJSON 数组是一个值列表。可以通过从数组中插入和删除 QJsonValue 来操作该列表。
QJsonObjectJSON 对象是键值对的列表,其中键是唯一的字符串,值由 QJsonValue 表示。
QJsonValue该类封装了 JSON 支持的数据类型。

QJsonValue

在 Qt 中 QJsonValue 可以封装的基础数据类型有六种(和 Json 支持的类型一致),分别为:

  • 布尔类型:QJsonValue::Bool
  • 浮点类型(包括整形): QJsonValue::Double
  • 字符串类型: QJsonValue::String
  • Json 数组类型: QJsonValue::Array
  • Json 对象类型:QJsonValue::Object
  • 空值类型: QJsonValue::Null

这些类型可以通过 QJsonValue 的构造函数被封装为一个类对象:

// Json对象
QJsonValue(const QJsonObject &o);
// Json数组
QJsonValue(const QJsonArray &a);
// 字符串
QJsonValue(const char *s);
QJsonValue(QLatin1String s);
QJsonValue(const QString &s);
// 整形 and 浮点型
QJsonValue(qint64 v);
QJsonValue(int v);
QJsonValue(double v);
// 布尔类型
QJsonValue(bool b);
// 空值类型
QJsonValue(QJsonValue::Type type = Null);

如果我们得到一个 QJsonValue 对象,如何判断内部封装的到底是什么类型的数据呢?这时候就需要调用相关的判断函数了,具体如下:

// 是否是Json数组
bool isArray() const;
// 是否是Json对象
bool isObject() const;
// 是否是布尔类型
bool isBool() const;
// 是否是浮点类型(整形也是通过该函数判断)
bool isDouble() const;
// 是否是空值类型
bool isNull() const;
// 是否是字符串类型
bool isString() const;
// 是否是未定义类型(无法识别的类型)
bool isUndefined() const;

通过判断函数得到对象内部数据的实际类型之后,如果有需求就可以再次将其转换为对应的基础数据类型,对应的 API 函数如下:

// 转换为Json数组
QJsonArray toArray(const QJsonArray &defaultValue) const;
QJsonArray toArray() const;
// 转换为布尔类型
bool toBool(bool defaultValue = false) const;
// 转换为浮点类型
double toDouble(double defaultValue = 0) const;
// 转换为整形
int toInt(int defaultValue = 0) const;
// 转换为Json对象
QJsonObject toObject(const QJsonObject &defaultValue) const;
QJsonObject toObject() const;
// 转换为字符串类型
QString toString() const;
QString toString(const QString &defaultValue) const;

QJsonObject

QJsonObject 封装了 Json 中的对象,在里边可以存储多个键值对,为了方便操作,键值为字符串类型,值为 QJsonValue 类型。

  • 如何创建空的 Json 对象
QJsonObject::QJsonObject();	// 构造空对象
  • 将键值对添加到空对象中
iterator QJsonObject::insert(const QString &key, const QJsonValue &value);
  • 获取对象中键值对个数
int QJsonObject::count() const;
int QJsonObject::size() const;
int QJsonObject::length() const;
  • 通过 key 得到 value
QJsonValue QJsonObject::value(const QString &key) const;    // utf8
QJsonValue QJsonObject::value(QLatin1String key) const;	    // 字符串不支持中文
QJsonValue QJsonObject::operator[](const QString &key) const;
QJsonValue QJsonObject::operator[](QLatin1String key) const;
  • 删除键值对
void QJsonObject::remove(const QString &key);
QJsonValue QJsonObject::take(const QString &key);	// 返回key对应的value值
  • 通过 key 进行查找
iterator QJsonObject::find(const QString &key);
bool QJsonObject::contains(const QString &key) const;

遍历,方式有三种:

  • 使用相关的迭代器函数
  • 使用 [] 的方式遍历,类似于遍历数组,[] 中是键值
  • 先得到对象中所有的键值,在遍历键值列表,通过 key 得到 value 值
QStringList QJsonObject::keys() const;

QJsonDocument

  1. 它封装了一个完整的 JSON 文档,并且可以从 UTF-8 编码的基于文本的表示以及 Qt 自己的二进制格式读取和写入该文档。
  2. QJsonObjectQJsonArray 这两个对象中的数据是不能直接转换为字符串类型的,如果要进行数据传输或者数据的持久化,操作的都是字符串类型而不是 QJsonObject 或者 QJsonArray 类型,我们需要通过一个 Json 文档类进行二者之间的转换。

下面依次介绍一下这两个转换流程应该如何操作:

1. QJsonObject 或者 QJsonArray ===> 字符串

  1. 创建 QJsonDocument 对象
QJsonDocument::QJsonDocument(const QJsonObject &object);
QJsonDocument::QJsonDocument(const QJsonArray &array);

可以看出,通过构造函数就可以将实例化之后的 QJsonObject 或者 QJsonArray 转换为 QJsonDocument 对象了。

  1. 将文件对象中的数据进行序列化
// 二进制格式的json字符串
QByteArray QJsonDocument::toBinaryData() const;	 
// 文本格式
QByteArray QJsonDocument::toJson(JsonFormat format = Indented) const;	

通过调用 toxxx() 方法就可以得到文本格式或者二进制格式的 Json 字符串了。

  1. 使用得到的字符串进行数据传输,或者磁盘文件持久化

2. 字符串 ===> QJsonObject 或者 QJsonArray

一般情况下,通过网络通信或者读磁盘文件就会得到一个 Json 格式的字符串,如果想要得到相关的原始数据就需要对字符串中的数据进行解析,具体解析流程如下:

  1. 将得到的 Json 格式字符串通过 QJsonDocument 类的静态函数转换为 QJsonDocument 类对象
[static] QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation = Validate);
// 参数文件格式的json字符串
[static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR);
  1. 将文档对象转换为 json 数组 / 对象
// 判断文档对象中存储的数据是不是数组
bool QJsonDocument::isArray() const;
// 判断文档对象中存储的数据是不是json对象
bool QJsonDocument::isObject() const
    
// 文档对象中的数据转换为json对象
QJsonObject QJsonDocument::object() const;
// 文档对象中的数据转换为json数组
QJsonArray QJsonDocument::array() const;
  1. 通过调用 QJsonArray , QJsonObject 类提供的 API 读出存储在对象中的数据。

关于 Qt 中 Json 数据对象以及字符串之间的转换的操作流程是固定的,我们在编码过程中只需要按照上述模板处理即可,相关的操作是没有太多的技术含量可言的。

实战

1. 手动写Json文件

注意:[…] 中是数组元素,{…}中是Json对象

在这里插入图片描述

2. 实现程序(从Json文件中读取数据,更改Json文件中的数据)

mainwindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    QVector<struct Animal> readJson();// 读取Json文件
    bool changeDate();// 改变Json文件中的数据

private:
    Ui::MainWindow *ui;
};
struct Food{
    QString stapleFood;
    QString meat;
};
struct Animal{
    QString name;
    int age;
    QVector<QString> eatTimeArr;
    struct Food food;
};

mainwindow.cpp


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    changeDate();
    readJson();
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 增加数据直接在手动修改Json文件

// 查数据(已知Json数据格式的情况下):将Json中所有animal类保存到vector中全部返回
QVector<struct Animal> MainWindow::readJson()
{
    QFile file("D:\\Qt\\homework\\text01\\studyJson.json");
    bool ret = file.open(QFile::ReadOnly);

    QByteArray bytes = file.readAll();// 把文件中所有数据读取出来
    QJsonDocument doc = QJsonDocument::fromJson(bytes);// 将读出的数据保存为Json文档
    QJsonArray groupArr = doc.array();// 获取数组
    QVector<struct Animal> ans;// 用于保存获取到的数据

   for(int i = 0; i < groupArr.size(); i++)
   {
       QJsonObject obj = groupArr.at(i).toObject();// 把数组中每一个数据都转化为 QJsonObject

       struct Animal animal;
       animal.name = obj.value("name").toString();
       animal.age = obj.value("age").toInt();

       // eatTime 对应的值为一个数组
       QJsonArray foodArr = obj.value("eatTime").toArray();
       for(int i = 0; i < foodArr.size(); i++)
       {
           animal.eatTimeArr.push_back(foodArr.at(i).toString());
       }

       // food 对应的值为一个 QJsonObject 类型
       QJsonObject subObj = obj.value("food").toObject();
       animal.food.stapleFood = subObj.value("stapleFood").toString();
       animal.food.meat = subObj.value("meat").toString();

       ans.push_back(animal);// 将获取到的数据加入容器中

       qDebug() << "name =" << animal.name
                << "age =" << animal.age
                << "eatTime =" << animal.eatTimeArr[0] << animal.eatTimeArr[1] << animal.eatTimeArr[2]
                << "food.stapleFood =" << animal.food.stapleFood
                << "food.meat =" << animal.food.meat;
   }
   return ans;
}


// 改数据:从studyJson.json读取数据并且富贵的年龄改为10岁
bool MainWindow::changeDate()
{
    // 打开文件
    QFile file("D:\\Qt\\homework\\text01\\studyJson.json");
    file.open(QIODevice::ReadWrite);


    QByteArray bytes = file.readAll();// 读取文件所有内容
    file.close();
    QJsonDocument doc = QJsonDocument::fromJson(bytes);// 将读出的数据保存为Json文档
    QJsonArray groupArr = doc.array();// 获取数组

    QJsonObject obj = groupArr.at(0).toObject();// 获取数组中第一个元素

    // 判断 "age"节点是否存在
    if(obj.contains("age")){
        obj["age"] = 10;// 将数组第一个元素中的年龄改变

        // 此时我们新建一个数组,把更新好的元素加入数组,并且把之前数组中没有改变的元素加入
        QJsonArray arr;
        arr.append(obj);
        arr.append(groupArr.at(1).toObject());

        // 保存至Json文档  注意:调用setArray后,先会把之前保存所有的数据清除,然后再保存新的数据
        doc.setArray(arr);
    }


    // 把最新数据写入QIODevice::Truncate
    file.open(QFile::WriteOnly|QFile::Truncate);
    file.seek(0);// 使写入位置为起始位置
    file.write(doc.toJson());
}

打印调试信息
在这里插入图片描述
执行changeDate()后,Json文件改变

这里需要注意:如果用Json自己写入文件,他所有数据会根据key的字典序排列

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/670390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Loki+Grafana(外)采集Kubernetes(K8s)集群(基于containerd)

一、Loki简介 1、简介 Loki Loki是一个开源、分布式的日志聚合系统&#xff0c;由Grafana Labs推出。Loki的设计目标是为了高效地处理大规模的日志数据&#xff0c;并具有良好的可扩展性。Loki的最大优点是它具有低资源占用和高效的查询速度。这是因为Loki不需要在处理日志数据…

工具篇6--kafka消息模型介绍

前言&#xff1a;kafka 诞生于需要处理大数据量的背景下&#xff0c;在当前的开发中&#xff0c;数据量的量级也是不断的提高&#xff0c;所以就非常有必要去研究一下kafka 的模型了&#xff1b; kafka 的官网先放一下&#xff1a; 1 英文官网&#xff1b; 2 中文网站&#xf…

Spring Boot 中使用 JSR-303 数据校验

Spring Boot 中使用 JSR-303 数据校验 在 Web 开发中&#xff0c;数据校验是一个非常重要的环节。它可以帮助我们在用户提交表单数据时验证数据的合法性&#xff0c;防止一些不必要的错误和漏洞。在 Spring Boot 中&#xff0c;我们可以使用 JSR-303 数据校验规范来实现数据校…

黑马程序员前端 Vue3 小兔鲜电商项目——(三)Layout 首页页面布局

文章目录 组件结构快速搭建首页组件结构Nav 组件Header 组件Footer 组件index.vue 中添加组件 字体图标渲染一级导航渲染封装接口函数渲染数据 吸顶导航交互实现安装 VueUser 插件组件静态结构添加组件实现吸顶交互 Pinia优化重复请求 组件结构快速搭建 首页组件结构 页面效果…

字节跳动的项目经理,是什么神仙存在?

早上好&#xff0c;我是老原。 要是说起项目经理的待遇天花板&#xff0c;你觉得会是什么样的&#xff1f; 在2022年&#xff0c;虽然很多互联网大厂都在大裁员&#xff0c;同时也刺激了更多人想进大厂的心。 就从项目经理这个岗位来看&#xff0c;你说大小厂的工作内容差距…

Win11的两个实用技巧系列之找不到项目的文件如何删除、无法用蓝牙耳机的多种解决办法

Win11 新预览版怎么恢复文件管理器经典功能? Win11 新预览版怎么恢复文件管理器经典功能&#xff1f;Win11最新版去掉了文件管理器经典功能&#xff0c;该怎么操作呢&#xff1f;下面我们就来看看详细的恢复方法 微软在日前发布的 Win11 Dev Build 23481 预览版更新中&#x…

建筑中的智能照明系统

【摘要】&#xff1a;建筑智能照明工程中智能照明控制系统发展迅速&#xff0c;具有舒适性和节能性两方面优势。智能照明控制系统已经处于模块化高速发展阶段&#xff0c;如今更好的控制方案成为制约系统发展的瓶颈。文章在研究了国内外智能照明系统的基础上&#xff0c;从照明…

Java 结合中文分词库 jieba 统计一堆文本中各个词语的出现次数【代码记录】

文章目录 1、需求2、代码3、结果 1、需求 2、代码 package com.zibo.main;import com.huaban.analysis.jieba.JiebaSegmenter;import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; import java.util.List; imp…

Picker, ColorPicker, DatePicker 的使用

1. Picker 选择器的使用 1.1 实现 /// 选择器 struct PickerBootcamp: View {State var selection: String "Most Recent"let filterOptions:[String] ["Most Recent", "Most Popular", "Most Liked"]init(){UISegmentedControl.ap…

Python基础(16)——Python集合(set)

Python基础&#xff08;16&#xff09;——Python集合&#xff08;set&#xff09; 文章目录 Python基础&#xff08;16&#xff09;——Python集合&#xff08;set&#xff09;目标一. 创建集合二. 集合常见操作方法2.1 增加数据2.2 删除数据2.3 查找数据 三. 总结 目标 创建…

Python基础(17)——Python运算符、公共方法、类型转换

Python基础&#xff08;17&#xff09;——Python运算符、公共方法、类型转换 文章目录 Python基础&#xff08;17&#xff09;——Python运算符、公共方法、类型转换目标一. 运算符1.1 1.2 *1.3 in或not in 二. 公共方法2.1 len()2.2 del()2.3 max()2.4 min()2.5 range()2.6 e…

4个重要的云安全方向

导语 伴随着云计算的不断发展和成熟&#xff0c;云安全越来越受到重视&#xff0c;每一年云安全都有不同的重点话题值得关注&#xff0c;今天我们一起来看看2023非常重要4个云安全话题 云攻击路径发现和威胁建模 随着攻击面的扩大&#xff0c;企业云安全的复杂性也会增加。为您…

一文搞懂 MySQL 中的常用函数及用法

0️⃣前言 MySQL是一种常用的关系型数据库管理系统&#xff0c;它提供了许多内置函数来处理数据。本文将介绍MySQL中的各种常用函数&#xff0c;包括字符串函数、日期函数、数学函数、聚合函数等。 文章目录 0️⃣前言1️⃣字符串函数1.1CONCAT函数1.2SUBSTRING函数1.3REPLACE函…

测试用例常用方法和选择原则

目录 前言&#xff1a; 一、等价类划分法 等价类思考步骤&#xff1a; 二、边界值 边界值的方法小结&#xff1a; 三、因果图法 因果图中的符号&#xff1a; 利用因果导出测试用例需要经过以下几个步骤&#xff1a; 四、判定表法 组成部分&#xff1a; 书写步骤&#xff1a; 五…

神经网络笔记

多分类问题 Softmax 高级优化算法 Adam Algorithm Intuition 每个参数有不同的学习率 卷积层 每个神经元只看前一层输入的一部分 原因&#xff1a; 1.更快的计算 2.需要更少的训练数据&#xff08;不容易过度拟合&#xff09; 模型评估 成本函数 分类 训练集用来训练…

【Python】数据库(创建库 访问 连接 创建表 编辑记录 案例:客户管理实现)

文章目录 * 库表与管理1.访问数据库1.1 连接与创建数据库1.2 创建表1.3 编辑表记录1.3.1 添加记录1.3.2 修改记录1.3.3 返回所有记录1.3.4 删除记录1.3.5 查询记录 1.4 案例&#xff1a;客户管理 SQLite 实现 * 库表与管理 1.访问数据库 SQLite 是 Python 自带的数据库管理模…

SpringBoot 如何使用 Spring Cloud Stream 处理事件

SpringBoot 如何使用 Spring Cloud Stream 处理事件 在分布式系统中&#xff0c;事件驱动架构&#xff08;Event-Driven Architecture&#xff0c;EDA&#xff09;已经成为一种非常流行的架构模式。事件驱动架构将系统中的各个组件连接在一起&#xff0c;以便它们可以相互协作…

【深度学习】5-4 与学习相关的技巧 - 正则化解决过拟合(权值衰减,Dropout)

机器学习的问题中&#xff0c;过拟合是一个很常见的问题。过拟合指的是只能拟合训练数据&#xff0c;但不能很好地拟合不包含在训练数据中的其他数据的状态。机器学习的目标是提高泛化能力&#xff0c;即便是没有包含在训练数据里的未观测数据也希望模型可以进行正确的识别。 …

皓文电子 | 智能制造领先企业的安全服务经验分享

皓文电子是一家为客户提供设计、生产、销售高端开关电源及各类功率变换产品的国家级高新技术企业&#xff0c;是国内智能制造领域的代表企业。其核心产品能与国际主流电源厂商竞争&#xff0c;达到国内外领先水平&#xff0c;并在国家多个重点项目中批量生产装备。 遭遇安全事件…

2023年湖北孝感初、中级工程师职称报名条件和要求是什么?启程别

2023年湖北孝感初、中级工程师职称报名条件和要求是什么&#xff1f;启程别 初级职称对于找工作很有帮助。现在&#xff0c;学历越来越高&#xff0c;仅有学历已经不能满足应聘需求。初级职称的获得并不难&#xff0c;有了职称也会让自己在找工作时更有竞争力。威信公号搜一下启…