Qt构建JSON及解析JSON

目录

一.JSON简介

JSON对象

JSON数组

二.Qt中JSON介绍 

QJsonvalue

Qt中JSON对象

Qt中JSON数组 

QJsonDocument

三.Qt构建JSON数组

 

 四.解析JSON数组


一.JSON简介

一般来讲C++类和对象在java中是无法直接直接使用的,因为压根就不是一个规则。但是他们在内存中都是二进制表示的,所以把C++的类和对象转成二进制再按照java的规则解析这段二进制代码就可以做到C++描述的东西在java中复现了。但是呢涉及到底层的东西都非常复杂,直接解析二进制非常困难,所以JSON应运而生,JSON是一种文本格式,文本格式相对来说比较接近人类语言规则,便于理解,同时能够将复杂的数据结构(如对象和数组)转换为一种通用的表示形式,使得不同语言之间的数据交换变得可行简化了各种语言数据之间的转换解析。JSON的作用可以通俗地举个例子,比如我有一个俄罗斯朋友,他不会中文,我不会俄文,所以我们之间写信既不能用中文也不能用俄文。但是我们都会英文,所以我可以把原先写好的中文信按照中文翻译成英文的规则翻译成英文,他接收到信件后可以按照英文翻译成俄文的规则进行解析阅读。所以JSON就是个桥梁中间过渡作用,便于不同语言之间数据的传输和交换。

JSON全称JavaScript Object Notation,JSON的名称中包含“JavaScript”,这表明它最初是为JavaScript设计的。JSON的语法是基于JavaScript的对象字面量表示法,因此它与JavaScript的结构非常相似,但是现在基本上和js没什么太大的关系了,规则早就独立出来了,基本上所有语言都支持JSON格式的构建和解析,不是js一家独有。

二.JSON格式

先来举个简单的例子

JSON一般来讲就JSON对象和JSON数组两种格式

JSON对象

JSON对象一般是以花括号包起来的 {  },里面成员都是键值对的形式。键必须是字符串类型,值可以是各种别的类型,也可以再嵌套一层JSON对象或者JSON数组。

JSON数组

JSON数组一般是以中括号包起来的[ ],里面的成员可以是各种不同的类型,包括:整型、浮点型、字符串、布尔类型、JSON数组、JSON对象

举个例子

{  "name": "Alice",  "age": 30,  "isStudent": false,  "courses": [  {  "courseName": "Mathematics",  "credits": 3,  "instructor": {  "name": "Dr. Smith",  "email": "smith@example.com"  }  },  {  "courseName": "Physics",  "credits": 4,  "instructor": {  "name": "Dr. Johnson",  "email": "johnson@example.com"  }  }  ]  
}

首先上面例子中整体是一个JSON对象因为最外层是花括号,JSON对象只能是键值对,这个JSON键值对有4个,键分别为name、age、isStudent、courses,courses的值为JSON数组类型,这个数组类型包了两个JSON对象,其中键为courseName、credits、instructor,而instructor又是一个JSON对象,键为name和email

二.Qt中JSON介绍 

QJsonvalue

QJsonValue 是一个可以持有多种JSON数据类型的值(如对象、数组、字符串、数字、布尔值和空值)的容器。这种设计使得 QJsonObject 和 QJsonArray 能够以统一的方式处理这些不同类型的值,而不需要为每个可能的类型提供单独的接口。

常见的成员函数

构造函数

QJonvalue支持多种类型构造,包括null空值构造(例子里的最后一个),所以在JSON对象和JSON的成员函数里如果有用到QJonvalue的是可以直接填自己常用的类型直接隐式类型转换的

判断内部封装是什么类型的函数

类型转换

Qt中JSON对象

Qt中用Qobject类来表示JSON对象

常见的成员函数如下

大部分成员函数都与C++的容器类差不多

构造函数及拷贝构造

赋值 

迭代器

查找

一般都只会用到第一个QString类型的key值去查找

 插入

 与容器插入也类似,如果插入的键key原本就存在,那么它的值会自动覆盖。如果是插入新的键值对会直接插入到对象中,但是是无序插入,不一定新的键值对就在对象的最末尾。Qt中没给指定迭代器insert插入

删除

删除有两种方式,迭代器删除或者直接给键的名称remove删除

重载方括号

此处的重载方括号是便于根据键去找值,所以方括号里面填的不是数组下标而是键的名称

通过key值得到value

遍历key

这个是获取所有键名称的,得到的键名称会直接放到QStringList中,与上面的通过key值得到value配合就可以知道所以键值对的情况了

举个打印键值对的例子

 

Qt中JSON数组 

Qt中用QJsonArray类来表示JSON数组,内部类型都为QJsonvalue

常见的成员函数

构造及拷贝构造

添加插入数组元素

追加的形式添加元素

尾插及头部插入

 insert指定位置插入

获取元素值

获取头部的值

获取尾部的元素值

 

获取指定位置的值

 

 

删除元素

头删尾删

 

 

删除指定位置元素

 

 

QJsonDocument

QJsonDocument封装了一个完整的JSON文档,可以从utf-8编码的基于文本的表示,以及Qt本身的二进制格式读取和写入该文档

前面的QJsonObject对象和QJsonArray可以当作QJsonDocument的一部分,不过整体处理还是通过QJsonDocument来进行处理的。使用 QJsonDocument::fromJson 方法解析 JSON 字符串或文件时,它会根据 JSON 数据的内容(是对象还是数组)来决定返回一个包含 QJsonObject 还是 QJsonArray 的 QJsonDocument 实例。然后,你可以检查返回的 QJsonDocument 是否包含对象或数组,并相应地将其转换为 QJsonObject 或 QJsonArray 进行进一步处理。构建JSON文件时也是对QJsonDocument对象进行转换

成员函数

构造函数可以通过JSON对象或者JSON数组直接构造

构建JSON字符串常用的函数

将QJsonDocument转成JSON字符串或者二进栈字符串

第一个是二进栈文件,第二、三都是转成JSON文件

 

解析JSON文件常用的函数

解析JSON文件一般分为两步,第一步是将JSON文件转换成QJsonDocument

第一种是从二进制数据的文档中解析JSON字符串,QJsonDocument::DataValidation validation(可选):指定数据验证的级别。默认是 QJsonDocument::Validate,意味着会进行完整的验证,这个一般都是自动补齐的,一般都用不到,直接用默认的就可以了。

第二种是从JSON格式的文本文件中解析JSON字符串,QJsonParseError *error(可选):指向 QJsonParseError 对象的指针,用于在解析过程中捕获错误信息这个也是直接用就可以了

第二步是将QJsonDocument文件具体解析成具体的 QJsonArray 或者 QJsonObject

与之相关的是先判断是数组还是对象然后才能具体解析

 

最后将 QJsonDocument具体转换成 QJsonArray 或者 QJsonObject

 

三.Qt构建JSON数组

 

{  "name": "Alice",  "age": 30,  "isStudent": false,  "courses": [  {  "courseName": "Mathematics",  "credits": 3,  "instructor": {  "name": "Dr. Smith",  "email": "smith@example.com"  }  },  {  "courseName": "Physics",  "credits": 4,  "instructor": {  "name": "Dr. Johnson",  "email": "johnson@example.com"  }  }  ]  
}

怎么将上面的JSON语句用Qt构建出来呢,可以利用JSON解析工具来理清结构JSON 在线解析、格式化、校验工具 (jsontool.cn)

正常未折叠是这样的

然后从上图可以看出来最外围是个对象,所以直接先构建一个QJsonObject对象出来

可以直接实例化也可以new对象出来,但是new出来一定要在最后释放掉

接着要处理JsonObject里面的东西了,但是因为有很多嵌套其实不好看清结构的,所以可以借助在线解析工具将一些暂时用不到的结构折叠起来

 

从上图可以看出来 JsonObject第二层有name,age,isStudent,courses四个东西,其中courses的值是QJsonArray 类型,可以要晚点处理,不能直接插入,但是剩余的三个都是正常的键值对,所以直接插入 JsonObject里就可以了

而对courses的处理,先构造出 QJsonArray 空数组出来,然后再一步步往里面插东西

 展开courses可以看出来里面是两个QJsonObject类型的Json对象

先处理第一个Object对象,也是先实例化出来

 

然后展开第一个Object看看里面的样子

 

从上图可以看出来前两个直接插入就可以了,而第三个成员又嵌套了一个Object对象,所以也得特殊处理,当instructor全部处理完了才能插入courses1中

 

courses2的操作与courses1操作类似所以就不多加赘述了

 

courses2处理完了就代表array处理完了,所以进行下一步插入操作了

 

完整代码如下

    QJsonObject* JsonObject=new QJsonObject();JsonObject->insert("name","Alice");JsonObject->insert("age","30");JsonObject->insert("isStudent","false");//courses数组处理QJsonArray array;//courses数组中第一个对象QJsonObject courses1;courses1.insert("courseName","Mathematics");courses1.insert("credits",3);QJsonObject instructor;   //courses1这个对象里面又嵌套了对象,所以也得特殊处理instructor.insert("name","Dr. Smith");instructor.insert("email","smith@example.com");courses1.insert("instructor",instructor);//处理完了进行插入//courses数组中第二个对象QJsonObject courses2;courses2.insert("courseName","Physics");courses2.insert("credits",4);QJsonObject instructor2;instructor2.insert("name","Dr. Johnson");instructor2.insert("email","johnson@example.com");courses2.insert("instructor",instructor2);array.push_back(courses1);//JsonArrary数组插入数据array.push_back(courses2);JsonObject->insert("courses",array);//array里面的成员全部处理完了,插入最外层对象// 当不再需要 JsonObject 时,使用 delete 删除它  delete JsonObject;  

 构建完了后转换成QJsonDocument,然后转换成JSON格式,打印一下看看内容

最后直接保存到文件里 

 四.解析JSON数组

一种解析方法是递归进行处理,不过打印出来是无序的,因为JSON对象本来就是无序的。不过因为太复杂了,而且容易出问题,如果是直接JSON文件是可以打开看到基本的JSON结构的,而从API接收数据一般会给一个JSON格式案例的,所以直接对照案例解析就可以了,递归是在完全不知道要解析JSON文件的格式的情况下才选择的

// 递归处理 JSON 数据
void parseJsonValue(const QJsonValue &value) {if (value.isObject()) {// 如果是对象,直接打印键值对QJsonObject obj = value.toObject();for (QString key : obj.keys()) {QJsonValue val = obj.value(key);// 直接打印键值对if (val.isBool()) {qDebug() << key << ":" << val.toBool();} else if (val.isDouble()) {qDebug() << key << ":" << val.toDouble();} else if (val.isString()) {qDebug() << key << ":" << val.toString();} else if (val.isNull()) {qDebug() << key << ":" << "null";} else if (val.isObject() || val.isArray()) {qDebug() << key << ": [Complex Type]";// 对于嵌套的对象或数组,继续递归parseJsonValue(val);}}} else if (value.isArray()) {// 如果是数组,遍历数组中的所有元素QJsonArray array = value.toArray();for (int i = 0; i < array.size(); ++i) {qDebug() << "Array index" << i << ":";parseJsonValue(array[i]); // 递归解析数组的元素}} else if (value.isBool()) {qDebug() << "Bool:" << value.toBool();} else if (value.isDouble()) {qDebug() << "Double:" << value.toDouble();} else if (value.isString()) {qDebug() << "String:" << value.toString();} else if (value.isNull()) {qDebug() << "Null";} else {qDebug() << "Unknown type";}
}
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QFile file("E:/Qt/q/content/untitled15/teacher.json");if (!file.open(QFile::ReadOnly | QFile::Text)) {qDebug() << "Could not open file";}QByteArray fileData = file.readAll();QJsonDocument doc = QJsonDocument::fromJson(fileData);if (!doc.isNull()) {if (doc.isObject()) {parseJsonValue(doc.object());} else if (doc.isArray()) {parseJsonValue(doc.array());} else {qDebug() << "Document is not an object or array";}} else {qDebug() << "Invalid JSON data";}}

 如果已经知道了格式该怎么解析

还是老演员例子

直接按图索骥,直接用键打印值就行

#include "widget.h"
#include "ui_widget.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QDebug>
#include <QFile>
#include <QStringList>// Widget类的构造函数
Widget::Widget(QWidget *parent): QWidget(parent) // 调用基类的构造函数, ui(new Ui::Widget) // 初始化UI界面
{ui->setupUi(this); // 设置UI界面// 打开JSON文件QFile file("E:/Qt/q/content/untitled15/teacher.json");if (!file.open(QFile::ReadOnly)) { // 如果文件打开失败qDebug() << "Could not open file"; // 打印错误信息return; // 退出构造函数}QByteArray Bit = file.readAll(); // 读取文件内容到QByteArrayQJsonDocument doc = QJsonDocument::fromJson(Bit); // 将QByteArray解析为QJsonDocumentif (doc.isObject()) { // 检查最外层是否是JSON对象QJsonObject object = doc.object(); // 获取JSON对象// 直接处理JSON对象中的每个字段if (object.contains("age") && object["age"].isString()) {qDebug() << "age:" << object["age"].toString(); // 打印年龄}if (object.contains("isStudent") && object["isStudent"].isString()) {qDebug() << "isStudent:" << object["isStudent"].toString();}if (object.contains("name") && object["name"].isString()) {qDebug() << "name:" << object["name"].toString(); // 打印姓名}// 处理courses数组if (object.contains("courses") && object["courses"].isArray()) {QJsonArray courses = object["courses"].toArray(); // 获取courses数组for (int i = 0; i < courses.size(); ++i) { // 遍历courses数组QJsonObject course = courses[i].toObject(); // 获取当前课程对象if (course.contains("courseName") && course["courseName"].isString()) {qDebug() << "Course Name:" << course["courseName"].toString(); // 打印课程名称}if (course.contains("credits") && course["credits"].isDouble()) {qDebug() << "Credits:" << course["credits"].toDouble(); // 打印学分}if (course.contains("instructor") && course["instructor"].isObject()) {QJsonObject instructor = course["instructor"].toObject(); // 获取讲师对象if (instructor.contains("name") && instructor["name"].isString()) {qDebug() << "Instructor Name:" << instructor["name"].toString(); // 打印讲师姓名}if (instructor.contains("email") && instructor["email"].isString()) {qDebug() << "Instructor Email:" << instructor["email"].toString(); // 打印讲师邮箱}}}}} else {qDebug() << "JSON root is not an object"; // 如果最外层不是对象,则打印错误信息}
}// Widget类的析构函数
Widget::~Widget()
{delete ui; // 清理UI资源
}

 

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

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

相关文章

使用 Internet 共享 (ICS) 方式分配ip

设备A使用dhcp的情况下&#xff0c;通过设备B分配ip并共享网络的方法。 启用网络共享&#xff08;ICS&#xff09;并配置 NAT Windows 自带的 Internet Connection Sharing (ICS) 功能可以简化 NAT 设置&#xff0c;允许共享一个网络连接给其他设备。 打开网络设置&#xff1…

灵当CRM系统index.php存在SQL注入漏洞

文章目录 免责申明漏洞描述搜索语法漏洞复现nuclei修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 漏洞描述 灵当CRM系统是一款功能全面、易于使用的客户关系管理&#xff08;C…

jacoco生成单元测试覆盖率报告

前言 单元测试是日常编写代码中常用的&#xff0c;用于测试业务逻辑的一种方式&#xff0c;单元测试的覆盖率可以用来衡量我们的业务代码经过测试覆盖的比例。 目前市场上开源的单元测试覆盖率的java插件&#xff0c;主要有Emma&#xff0c;Cobertura&#xff0c;Jacoco。具体…

2025年最新大数据毕业设计选题-Hadoop综合项目

选题思路 回忆学过的知识(Python、Java、Hadoop、Hive、Sqoop、Spark、算法等等。。。) 结合学过的知识确定大的方向 a. 确定技术方向&#xff0c;比如基于Hadoop、基于Hive、基于Spark 等等。。。 b. 确定业务方向&#xff0c;比如民宿分析、电商行为分析、天气分析等等。。。…

Docker操作MySQL

1&#xff0c;拷贝&#xff1b; docker cp mysql01:/etc/mysql .2&#xff0c;修改conf.d和mysql.conf.d文件 3&#xff0c; vim mysql/my.cnf 4&#xff0c;拷贝并替换my.cnf文件 5&#xff0c;mysql镜像重启命令&#xff1a; docker exec -it mysql01 -uroot -p0000006&…

MySQL篇(运算符)(持续更新迭代)

目录 一、简介 二、运算符使用 1. 算术运算符 1.1. 加法运算符 1.2. 减法运算符 1.3. 乘法与除法运算符 1.4. 求模&#xff08;求余&#xff09;运算符 2. 比较运算符 2.1. 等号运算符 2.2. 安全等于运算符 2.3. 不等于运算符 2.4. 空运算符 2.5. 非空运算符 2.6.…

万字长文——ConvNeXt(2022CVPR),卷积网络的顶峰之作,在Transformer盛行的当下,卷积网络还能再战!

ConvNext:A ConvNet for the 2020s ConvNext:2020 年代的卷积神经网络 论文地址: https://arxiv.org/pdf/2201.03545 自从Transformer成功应用在视觉领域并且取得显著成绩后,很多人开始抛弃卷积网络架构,转而使用Transformer。然而有的大佬不认为卷积过时了,于是有了这篇…

【工具变量】科技金融试点城市DID数据集(2000-2023年)

时间跨度&#xff1a;2000-2023年数据范围&#xff1a;286个地级市包含指标&#xff1a; year city treat post DID&#xff08;treat*post&#xff09; 样例数据&#xff1a; 包含内容&#xff1a; 全部内容下载链接&#xff1a; 参考文献-pdf格式&#xff1a;https://…

[Visual Stuidio 2022使用技巧]2.配置及常用快捷键

使用vs2022开发WPF桌面程序时常用配置及快捷键。 语言&#xff1a;C# IDE&#xff1a;Microsoft Visual Studio Community 2022 框架&#xff1a;WPF&#xff0c;.net 8.0 一、配置 1.1 内联提示 未开启时&#xff1a; 开启后&#xff1a; 开启方法&#xff1a; 工具-选…

每日刷题(算法)

我们N个真是太厉害了 思路&#xff1a; 我们先给数组排序&#xff0c;如果最小的元素不为1&#xff0c;那么肯定是吹牛的&#xff0c;我们拿一个变量记录前缀和&#xff0c;如果当前元素大于它前面所有元素的和1&#xff0c;那么sum1是不能到达的值。 代码&#xff1a; #def…

python - 子类为什么调用父类的方法

菜鸟教程 - 面向对象https://www.runoob.com/python3/python3-class.html为什么写这个呢 &#xff0c;因为很多时候&#xff0c;事情很简单&#xff0c;但我往往记住了使用方式&#xff0c;忘记了使用原因&#xff0c;也因为自己看到super()时&#xff0c;也想问为什么要用supe…

AJAX(一)HTTP协议(请求响应报文),AJAX发送请求,请求问题处理

文章目录 一、AJAX二、HTTP协议1. 请求报文2. 响应报文 三、AJAX案例准备1. 安装node2. Express搭建服务器3. 安装nodemon实现自动重启 四、AJAX发送请求1. GET请求2. POST请求(1) 配置请求体(2) 配置请求头 3. 响应JSON数据的两种方式(1) 手动&#xff0c;JSON.parse()(2) 设置…

Python 实现Excel XLS和XLSX格式相互转换

在日常工作中&#xff0c;我们经常需要处理和转换不同格式的Excel文件&#xff0c;以适应不同的需求和软件兼容性。Excel文件的两种常见格式是XLS&#xff08;Excel 97-2003&#xff09;和XLSX&#xff08;Excel 2007及以上版本&#xff09;。本文将详细介绍如何使用Python在XL…

【数据结构篇】~链表算法题3(环形链表)

链表算法题3&#xff08;环形链表&#xff09; 环形链表的证明1. 环形链表I​1) 思路2&#xff09;代码实现 2. 环形链表II​1) 思路11) 思路22&#xff09;代码实现 3. 随机链表的复制​1) 思路2&#xff09;代码实现 环形链表的证明 1. 环形链表I​ https://leetcode.cn/prob…

Redhat 7,8系(复刻系列) 一键部署Oracle21c-xe rpm

Oracle21c-xe前言 无论您是开发人员、DBA、数据科学家、教育工作者,还是仅仅对数据库感兴趣,Oracle Database Express Edition (XE) 都是理想的入门方式。它是全球企业可依赖的强大的 Oracle Database,提供简单的下载、易于使用和功能齐全的体验。您可以在任何环境中使用该…

git push出错Push cannot contain secrets

报错原因&#xff1a; 因为你的代码里面包含了github token明文信息&#xff0c;github担心你的token会泄漏&#xff0c;所以就不允许你推送这些内容。 解决办法&#xff1a; 需要先把代码里面的github token信息删除掉&#xff0c;并且删掉之前的历史提交&#xff0c;只要包…

Stable Diffusion Fooocus批量绘图脚本

当当当挡~&#xff0c;流动传热数值计算之余发布点AIGC相关文章&#xff0c;希望大家能喜欢~ 1 Stable Diffusion各种UI分析对比 提示&#xff1a;此部分主要是对SD各种界面的简要介绍和对比&#xff0c;只关注Fooocus批量绘图的读者可直接跳到第二部分。 Stable Diffusion …

微服务_入门2

文章目录 一、Feign远程调用二、Gateway服务网关2.1、为什么需要网关2.2、gateway快速入门2.3、断言工厂2.4、过滤器 一、Feign远程调用 来看我们以前利用RestTemplate发起远程调用的代码&#xff1a; 存在下面的问题&#xff1a; 代码可读性差&#xff0c;编程体验不统一&…

周末愉快!——周复盘

加班的晚上有一个美梦&#xff01; 周末愉快简单复盘结尾 精华&#xff1a; 在这个信息爆炸的时代&#xff0c;我们的大脑每天都被无数的数据和刺激充斥&#xff0c;以至于我们常常感到应接不暇。然而&#xff0c;正如古人所言&#xff1a;“不飞则已&#xff0c;一飞冲天”&am…

2025年最新大数据毕业设计选题-基于Spark分析相关

选题思路 回忆学过的知识(Python、Java、Hadoop、Hive、Sqoop、Spark、算法等等。。。) 结合学过的知识确定大的方向 a. 确定技术方向&#xff0c;比如基于Hadoop、基于Hive、基于Spark 等等。。。 b. 确定业务方向&#xff0c;比如民宿分析、电商行为分析、天气分析等等。。。…