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资源
}
相关文章:

Qt构建JSON及解析JSON
目录 一.JSON简介 JSON对象 JSON数组 二.Qt中JSON介绍 QJsonvalue Qt中JSON对象 Qt中JSON数组 QJsonDocument 三.Qt构建JSON数组 四.解析JSON数组 一.JSON简介 一般来讲C类和对象在java中是无法直接直接使用的,因为压根就不是一个规则。但是他们在内存中…...

合宙Air201模组LuatOS扩展功能:温湿度传感器篇!
通过前面几期的学习,同学们的学习热情越来越高。 合宙Air201模组除了支持3种定位方式外,还具有丰富的扩展功能,比如:通过外扩BTB链接方案,最多可支持21个IO接口:SPI、I2C、UART等多种接口全部支持。 本期…...
主流敏捷工具scrum工具
在当今的快速变化和高需求的业务环境中,敏捷开发已经成为许多企业实现快速迭代和响应市场需求的重要方法。而在众多敏捷工具中,选择适合自己团队的工具尤为重要。 今天,我们将对比几款主流的敏捷工具,供参考 1. Leangoo领歌&…...
探索微服务架构:从理论到实践,深度剖析其优缺点
微服务架构(Microservice Architecture)是一种软件开发架构形式,它的核心 思想是将大型应用程序拆分成一组小的服务,每个服务都运行在其独立的进程中,并且 服务与服务之间通过轻量级的通信机制(如HTTP REST…...

2024 年最佳 Chrome 验证码扩展,解决 reCAPTCHA 问题
验证码,特别是 reCAPTCHA,已成为在线安全的不可或缺的一部分。虽然它们在区分人类和机器人方面起着至关重要的作用,但它们也可能成为合法用户和从事网络自动化的企业的主要障碍。无论您是试图简化在线体验的个人,还是依赖自动化工…...
Go语言现代web开发defer 延迟执行
The defer statement will delay the execution of a function until the surrounding function is completed. Although execution is postponed, funciton arguments will be evaluated immediately. defer语句将延迟函数的执行,直到周围的函数完成。虽然执行被延…...

Vue路由二(嵌套多级路由、路由query传参、路由命名、路由params传参、props配置、<router-link>的replace属性)
目录 1. 嵌套(多级)路由2. 路由query传参3. 路由命名4. 路由params传参5. props配置6. <router-link>的replace属性 1. 嵌套(多级)路由 pages/Car.vue <template><ul><li>car1</li><li>car2</li><li>car3</li></ul…...

【RabbitMQ】可靠性传输
概述 作为消息中间件来说,最重要的任务就是收发消息。因此我们在收发消息的过程中,就要考虑消息是否会丢失的问题。结果是必然的,假设我们没有采取任何措施,那么消息一定会丢失。对于一些不那么重要的业务来说,消息丢失…...

【论文阅读】PERCEIVER-ACTOR: A Multi-Task Transformer for Robotic Manipulation
Abstract transformers凭借其对大型数据集的扩展能力,彻底改变了视觉和自然语言处理。但在机器人操作中,数据既有限又昂贵。通过正确的问题表述,操纵仍然可以从变形金刚中受益吗?我们使用peract来研究这个问题,peract…...
Linux 常用指令
Linux 常用指令 这是本人在备战 CSP 初赛做 Linux 指令题时,心血来潮整理的,希望对大家有帮助。如有错误或有补充,麻烦私信或评论指出。 表格按字母顺序排列 命令作用alias对命令重命名cal显示日历的指令cat查看文本文件的内容cd改变当前工…...

使用 PHPstudy 建立ThinkPHP8 本地集成环境
安装Composer 下载地址:https://getcomposer.org/Composer-Setup.exehttps://getcomposer.org/Composer-Setup.exe 打开PHPstudy创建网站: cmd终端进入PHPstudy www根目录下: 执行代码:cd phpstudy www 根目录地址 cd C:\phpst…...
【系统架构设计】软件的知识产权保护+标准化概论+应用数学+云计算
【系统架构设计】软件的知识产权保护标准化概论应用数学云计算 软件的知识产权保护标准化概论应用数学云计算 软件的知识产权保护 在该部分内容中,以下几点需要注意: 如果作品是委托创作的,著作权的归属应通过委托人和受托人之间的合同来确…...

解决使用阿里云DataV Geo在线地图路径访问403问题
文章目录 1. DataV Geo在线地图路径访问403问题2. 解决方法3. 重启生效 1. DataV Geo在线地图路径访问403问题 最近在写一个省市下钻的demo,用到的是 阿里云DataV Geo在线地图 去动态获取GeoJSON 省市的数据,如下代码 axios.get("https://geo.dat…...
linux 使用SSH密钥配置免密登录
需求:多台主机SSH免密登录,需要使用同一个密钥对 操作: 在Linux中,使用SSH密钥对来在多台主机之间配置免密登录。以下是配置步骤: 在你的本地机器上生成一个SSH密钥对。如果你已经有一个,你可以跳过这一…...
python教程(二):python数据结构大全(附代码)
Python 中数据结构的重要性不言而喻,它们是构建高效、可维护代码的基础。数据结构决定了如何存储、组织和操作数据。理解和使用合适的数据结构能够极大地提升程序的性能、简洁性以及代码的可读性。 Python 的基础数据结构有 4 种,分别是 列表 (list)、元…...

MySQL基于GTID同步模式搭建主从复制
系列文章目录 rpmbuild构建mysql5.7.42版本的rpm包 文章目录 系列文章目录一、mysql-5.7.42RPM包构建二、同步模式分类介绍1.异步同步模式2.半同步模式2.1.实现半同步操作流程2.2.半同步问题总结2.3.半同步一致性2.4.异步与半同步对比 3.GTID同步 三、GTID同步介绍1.gtid介绍2…...
RecyclerView的子项长按选择功能
在Android开发中,实现RecyclerView的子项长按选择功能通常涉及到几个关键步骤:设置RecyclerView的ItemTouchListener来监听长按事件,管理选中状态,以及更新UI以反映选中状态。以下是一个基本的实现步骤和示例代码。 1. 定义数据模…...

mongoDB-1
文章目录 一、疑似坑1.11.2 mongo ops manager1.3 mongo features视图固定大小集合(有点类似ringbuffer数据结构,capped collections)(聚簇集合)clustered collection(类比到Mysql的聚簇索引)聚合管道 aggregation pipelineWiredTiger (默认存…...

iKuai使用及设置流程
iKuai使用及设置流程 iKuai安装步骤 一、配置主机 1.电脑连接ETH0网口 2.ETH1网口连接猫上面的千兆口 3.手动配置pc的IP地址和192.168.1.1./24在同一网段 3.浏览器输入192.168.1.1 admin admin 二、外网设置 1.直接联通电信网络设置 2.点击 网络设置-内外网设置-点击接…...
【乐企-业务篇】销项开票接口声明(主要是业务对接)
我们系统销项对接了四家,所以抽象出来一个接口 专门用来定义销项相关的接口声明 代码如下 import java.util.List;/*** User: yanjun.hou* Date: 2024/9/4 10:07* Description:开票策略*/ public interface InvoiceStrategy {/*** 开票** @param order...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...