Qt- JSONXML

devtools/2024/10/22 3:36:19/

1. JSON概述

  • JSON(JavaScript Object Notation, JS 对象简谱)是一种轻量级的数据交换格式。

  • JSON 采用 key-value 的结构来组织和管理数据。

  • JSON 支持的数据类型: 数值型、字符串、布尔值、数组、对象等

    • JSON 来源于 JavaScript

  • JSON应用领域: 不同系统间数据的传递、 应用程序的配置文件

a.json

补充说明:

  • 以大括号包裹的数据叫做对象 {}

  • 以方括号包裹的数据叫做数组 []

2. 读取 JSON

读取 json文档所需的类:

  • QJsonDocument:Json 文档类,能将 json 格式的字符串转为 JSON 对象

    • fromJson(jsonStr); 将json字符串转为 json 文档 (静态方法)

    • object(); 将json文档转为 json对象

  • QJsonObject: Json 对象类

    • keys: 获取 json对象中的所有key

    • value("key") : 根据 key 的名称获取对应的值

  • QJsonArray: Json 数组类

  • QJsonValue: Json 值

    • isString() \ isDouble() \ isObject() \ isArray()

    • toArray() : 将 key 对应的值转为数组

    • toObject() : 将 key 对应的值转为对象

 示例1: 读取 userinfo.json 中基础类型数据

// 读取 json 文件
QFile file(":/files/userinfo.json");
if (!file.open(QIODevice::ReadOnly))
{qDebug() << "json文件读取失败";return;
}
QByteArray buf = file.readAll();// 将 json字符串转为 json文档
QJsonDocument jsonDoc = QJsonDocument::fromJson(buf);// 将json文档转为 json对象
QJsonObject rootObj = jsonDoc.object();// 使用 value 方法,根据 key 值读取数据
qDebug() << rootObj.value("id") << rootObj.value("id").toInt();
qDebug() << rootObj.value("name") << rootObj.value("name").toString();
qDebug() << rootObj.value("isMarry") << rootObj.value("isMarry").toBool();

示例2: 读取 userinfo.json 中所有数据

QFile file(":/files/userinfo.json");
if (!file.open(QIODevice::ReadOnly))
{qDebug() << "打开json文件失败";return;
}
QString jsonStr = file.readAll();// 将 json格式的字符串保存到 jsonDoc 中
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonStr.toUtf8());
QJsonObject root = jsonDoc.object();// 获取根节点下的子节点
QStringList keys = root.keys();// 遍历子节点
for (int i = 0; i < keys.size(); i++)
{QJsonValue value = root.value(keys[i]);if (value.isString()){qDebug() << "字符串" << value.toString();}else if (value.isDouble()){qDebug() << "数值型" << value.toDouble();}else if (value.isBool()){qDebug() << "布尔型" << value.toBool();}else if (value.isObject()){QJsonObject subObj = value.toObject();QStringList subKeys = subObj.keys();for(auto subKey : subKeys){qDebug() << subObj.value(subKey);}}else if (value.isArray()){qDebug() << "数组";QJsonArray arr = value.toArray();for (int j = 0; j < arr.size();j++){qDebug() << arr[j].toString();}qDebug() << "数组结束";}
}

3. 创建 JSON

创建 json 文档所需的类:

  • QJsonDocument:

    • toJson(); 将 json 对象转为 json 字符串

  • QJsonObject: Json 对象类

    • insert(key, value); 向节点中添加子节点

  • QJsonArray: Json 数组类

    • append(); 向数组中追加单元

示例:

// 创建根节点
QJsonObject rootObj;// 向根节点中添加节点
rootObj.insert("name", "韩梅梅");
rootObj.insert("age", 8);// 创建数组类型节点
QJsonArray hobbies;
// 向节点中追加数据
hobbies.append("LOL");
hobbies.append("打篮球");
// 将节点添加到上级节点中
rootObj.insert("hobbies", hobbies);// 创建对象类型节点
QJsonObject addr;
// 向节点中添加数据
addr.insert("city", "西安市");
addr.insert("area", "未央区");
// 将节点添加到上级节点中
rootObj.insert("addr", addr);// 将根节点转换为 json 文档对象
QJsonDocument jsonDoc(rootObj);
// 将json文档对象转换为字符串
QByteArray jsonStr = jsonDoc.toJson(QJsonDocument::Indented);// 将字符串写入 .json 文件中
QFile file("d:/a.json");
if (!file.open(QIODevice::WriteOnly))
{qDebug() << "打开文件失败";return;
}
file.write(jsonStr);
file.close();

4. XML概述

  • XML(Extensible Markup Language,可扩展标记语言),是一种类似于HTML的标记语言

    • html 都是系统预定义好的标签

    • xml 都是自定义的标签

  • XML是用来传输数据、保存数据,而不是显示数据。

  • XML的标签没有被预定义,用户需要在使用时自行进行定义。

  • XML是W3C(万维网联盟)的推荐标准。XML使用的树形结构更能表现出数据的包含关系

Qt 提供了两种方案来处理 XML 文档:

  • DOM 方式

  • QXmlStreamReader 和 QXmlStreamWriter

重点:要在项目中操作 xml 文档,需要在 .pro 文档中加入 xml 模块

QT += core gui xml

  • html: 超文本标记语言 (标签) 系统提前定义好的,每个标签都有不同的功能

  • xml:可扩展标记语言 (标签) 程序员自定义的标签,因为系统不认识自定义标签,所以不用来显示,而是用来保存数据的

5. DOM 方式

  • DOM(Document Object Model,即文档对象模型)

  • DOM 方式是将 XML 文档转换成应用程序可以遍历的树形结构,就可以访问其中的节点

  • 缺点:将整个XML文档读入内存,消耗内存较多

5.1 载入 XML

  • 使用 DOM 方式操作 XML,首先需要将 xml 文档载入,并保存到内存中

  • 使用 QDomDocument 配合 QFile 进行文件读取即可

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 1. 通过文件操作,将xml文档的内容读取出来并保存到内存中QDomDocument doc;// 加载 xml 文档,并以只读方式打开QFile file("./files/books.xml");if (!file.open(QIODevice::ReadOnly)){qDebug() << "读取XML文档失败";return;}// 将 XML 文档中的内容读取出来并以树形结构保存到 doc 中if (!doc.setContent(&file)){qDebug() << "载入xml文档失败";file.close();return;}// 因为xml文档内容已经读取到内存当中了,所以可以关闭文件操作file.close();}

5.2 读取 xml 头部

目标: 获取 <?xml version="1.0" encoding="utf-8"?> 中的信息

  • xml 文档中的每个标签、属性、内容都称为节点

  • 节点的基类为 QDomNode

    • 标签又叫做 标签节点(元素节点) 【QDomElement】

    • 属性又叫做属性节点 【QDomAttr】 (attribute)

    • 内容又叫做内容节点 【QDomText】

  • 重要方法:

    • nodeName() : 获取节点名称

    • nodeValue() : 获取节点值

    • nodeType() : 获取节点类型

QDomNode firstNode = doc.firstChild();
qDebug() << firstNode.nodeName();

5.3 读取根节点

  • xml 一般都有一个根节点, 在 books.xml 中,根节点为 library

  • 读取根节点的方法为 : doc.documentElement()

    • QDomElement 对象的 tagName 也能获取节点名称

QDomElement rootElement = doc.documentElement();
qDebug() << rootElement.tagName() << rootElement.nodeName() << rootElement.nodeValue() << rootElement.nodeType();

5.4 读取根节点下的子标签节点

核心方法:

  • isElement() : 判断是否为标签节点(元素节点)

  • nextSiblingElement() :获取下一个兄弟元素节点

  • toElement() : 将一个 QDomNode 节点转换为 QDomElement 节点。 (toAttr, toText)

  • qPrintable() : 使用该方法打印字符串时,没有引号

// 读取根节点
QDomElement rootElement = doc.documentElement();
// 获取根节点下的第一个子节点
QDomNode node = rootElement.firstChild();// 遍历子节点
while (node.isElement())
{// 将子节点转为元素节点QDomElement e = node.toElement();// 打印节点名称 和 id 属性值qDebug() << qPrintable(e.nodeName()) << e.nodeName() << e.attribute("id");// 找到下一个兄弟节点,并替换到 node 中,方便循环node = node.nextSiblingElement();
}

5.5 遍历深层子节点

childNodes() : 该方法能够获取一个节点下所有的子节点,并返回一个 QDomNodeList 对象

// 读取根节点
QDomElement rootElement = doc.documentElement();QDomNode node = rootElement.firstChild();// 遍历子节点
while (node.isElement())
{QDomElement e = node.toElement();// 获取当前节点下所有的子节点QDomNodeList list = e.childNodes();// 遍历 list for (int i = 0; i < list.size(); i++){// 每得到一个节点,就将其转换为 DomElement 节点,通过 text 方法能够得到它的内容QDomNode tmpNode = list.at(i);QDomElement tmpEle = tmpNode.toElement();qDebug() << tmpEle.nodeName() << tmpEle.text();}node = node.nextSiblingElement();
}

5.6 获取同名节点

elementsByTagName("标签名") : 该方法能够一次性获取 xml 文档中所有的同名元素节点

QDomNodeList list = doc.elementsByTagName("name");for (int i = 0; i < list.size(); i++)
{QDomNode node = list.at(i);QDomElement ele = node.toElement();qDebug() << ele.tagName() << ele.text();
}

5.7 创建 xml 文档

核心思路: (内存中操作,最后写文件)

  1. 创建一个 QDOMDocument 对象 (doc),该对象保存在内存中

  2. 向 doc 对象中添加节点

  3. 将 doc 对象写入一个 xml 文档中

QDomDocument doc;// 创建头部 并将 头部添加到 doc 中
QDomProcessingInstruction head = doc.createProcessingInstruction("xml", "verison='1.0' encoding='utf-8'");
doc.appendChild(head);// 创建根节点
QDomElement bookEle = doc.createElement("book");
bookEle.setAttribute("id", "01");
// 将book标签添加到文档中
doc.appendChild(bookEle);// 创建name节点,加入到 book 节点中
QDomElement nameEle = doc.createElement("name");
QDomText t = doc.createTextNode("盗墓笔记");
nameEle.appendChild(t);
bookEle.appendChild(nameEle);// 创建 author 节点,加入到 book 节点中
QDomElement authorEle = doc.createElement("author");
t = doc.createTextNode("南派三叔");
authorEle.appendChild(t);
bookEle.appendChild(authorEle);// 使用 QTextStream 流来写文件
QFile file("./files/test.xml");
file.open(QIODevice::WriteOnly);QTextStream out(&file);
// 参数1: 流对象
// 参数2: 子节点缩进
doc.save(out, 4);

6. 流方式(了解)

QXmlStreamReader : 使用流方式读取 XML 文档内容

QXmlStreamWriter : 使用流方式写 XML 文档

6.1 读取xml

执行逻辑: 流读取器(QXmlStreamReader )就是将XML文档报告为一个记号(tokens)流,通过循环从读取器中一个接一个的拉出记号。通过区分记号的类型,来实现 XML 文档的读取。

核心方法:

  • readNext(): 从xml输入流中读取下一个记号。

  • name(): 记号的名称,即<名称></名称>

  • isStartElement():判断当前已读取的记号是否为开始元素,开始元素即<>

  • isEndElement():判断当前已读取的记号是否为结束元素,结束元素即</>

  • readElementText():读取当前记号对应的文本值,<>文本值</>

  • atEnd():判断是否为文件结尾。

// 以只读方式打开 xml 文件
QFile file("./files/books.xml");
if(!file.open(QIODevice::ReadOnly))
{qDebug() << "读取xml文件失败";
}
// 读取文件内容  QXmlStreamReader
// reader对象中保存了所有的记号
reader.setDevice(&file);// 使用循环方式来依次获取所有的记号
while (!reader.atEnd())
{// 获取本次循环得到的记号QXmlStreamReader::TokenType type = reader.readNext();// 区分记号// 判断当前记号是否为 xml的头部if (type == QXmlStreamReader::StartDocument){qDebug() << reader.documentVersion() << reader.documentEncoding();}// 判断当前记号是否为 开始标签if (type == QXmlStreamReader::StartElement){qDebug() << '<' << reader.name() << '>';      // <user>if (reader.attributes().hasAttribute("id")){qDebug() << reader.attributes().value("id");}}if (type == QXmlStreamReader::EndElement){qDebug() << "</" << reader.name() << '>';     // </user>}if (type == QXmlStreamReader::Characters && !reader.isWhitespace()){qDebug() << reader.text();}}file.close();

6.2 写XML

QXmlStreamWriter : 使用流方式写 XML 文档

常用方法:

  • writeStartDocument():写文档头,作用类似于创建一个xml文档,并在文档开头部分写入版本信息和编码信息默认为:<?xml version="1.0" encoding="UTF-8"?>

  • writeEndDocument(): 对应于writeStartDocument(),当调用这个函数时,即表示文档信息写入完毕。

  • writeStartElement(): 写入开始记号 比如 <name>

  • writeEndElement(): 写入结束记号 比如 </name>

  • writeCharacters(): 向已有的标签中写入内容

  • writeTextElement(): 写入标签的同时写入标签的内容

QFile file("./files/test2.xml");
if(!file.open(QIODevice::WriteOnly)
{qDebug() << "打开文件失败";return;
}QXmlStreamWriter write(&file);
// 设置是否需要格式化
write.setAutoFormatting(true);
// 写头部 xml 标签
write.writeStartDocument();
// 写开始标签
write.writeStartElement("book");
// 给开始标签设置属性
write.writeAttribute("title", "哈哈哈");
// 给标签book标签内些内容
write.writeTextElement("name", "张三三");
// 标签结束
write.writeEndElement();// 整个文档结束
write.writeEndDocument();// 关闭文件
file.close();

 


http://www.ppmy.cn/devtools/127722.html

相关文章

Linux系统基础-动静态库

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux系统基础-动态库和静态库 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 动…

Vue 组件 view-shadcn-ui 2024.1.1 发布

Vue 组件 view-shadcn-ui 2024.1.1 发布 View Shadcn UI 是一个基于 Shadcn UI 和 Tailwind CSS 构建的组件库。 推荐一套为 Java 开发人员提供方便易用的 SDK 来与目前提供服务的的 Open AI 进行交互组件&#xff1a;https://github.com/devlive-community/openai-java-sdk 推…

面试官:`interrupted()` 和 `isInterrupted()` 你真的用懂了吗?

感谢Java面试教程的 Java面试题&#xff1a;interrupted和isInterrupted方法的区别 在Java中&#xff0c;interrupted() 和 isInterrupted() 是用于检查线程中断状态的方法&#xff0c;但它们之间有一些关键的区别。 方法类型&#xff1a; interrupted() 是一个静态方法&…

深度学习--CNN实现猫狗识别二分类(附带下载链接, 长期有效)

1. 代码实现(包含流程解释) 样本量: 8005 # # 1.导入数据集(加载图片)数据预处理# 进行图像增强, 通过对图像的旋转 ,缩放,剪切变换, 翻转, 平移等一系列操作来生成新样本, 进而增加样本容量, # 同时对图片数值进行归一化[0:1] from tensorflow.keras.preprocessing.image …

2018年计算机网络408真题解析

第一题&#xff1a; 解析&#xff1a;TCP/IP体系结构应用层常用协议及其相应的运输层协议 TCP协议是面向连接可靠数据传输服务&#xff0c;UDP无连接不可靠的数据传输服务&#xff0c;IP无连接不可靠的数据连接服务。 FTP协议&#xff0c;SMTP协议和HTTP协议使用TCP协议提供的面…

Axure大屏可视化模板:打造跨领域数据分析平台的原型设计案例

数据可视化已成为各行各业提升管理效率、优化决策过程的重要手段。Axure作为一款强大的原型设计工具&#xff0c;其大屏可视化模板在农业、园区、城市、企业数据可视化、医疗等多个领域得到了广泛应用。本文将通过几个具体案例&#xff0c;展示Axure大屏可视化模板在不同领域中…

【CHI】CHI协议自问自答

学习CHI有一段时间了&#xff0c;如今回过头来&#xff0c;再读协议&#xff0c;一些问题做个记录。如果有错误的地方&#xff0c;欢迎指正。如果有其他的问题&#xff0c;也欢迎留言讨论。 spec&#xff1a; IHI0050F_amba_chi_architecture_spec 【持续更新ing】 目录 1. …

基于机器学习的二手车价格因素识别与预测

1.项目背景 随着二手车市场的快速发展&#xff0c;消费者对二手车的需求逐渐增加&#xff0c;然而&#xff0c;由于二手车的定价涉及多种复杂因素&#xff0c;不同条件下的车辆价值差异较大&#xff0c;如何精准地评估二手车的市场价值成为了一个亟待解决的问题。本项目通过数…