Qt- JSONXML

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();

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5模型导入面板解读

1.Skeletal Mesh&#xff1a; 是一个可以让模型动起来的选项&#xff0c;适用于需要动画的角色或生物。是否勾选&#xff1a;如果导入的是一个需要动画的角色或生物&#xff0c;就勾选 Skeletal Mesh 选项&#xff1b;如果是静态物体&#xff0c;就不勾选。 2.Build Nanite&a…

【在Linux世界中追寻伟大的One Piece】Jsoncpp|序列化

目录 1 -> Jsoncpp 1.1 -> 特性 1.2 -> 安装 2 -> 序列化 3 -> 反序列化 4 -> Json::Value 1 -> Jsoncpp Jsoncpp是一个用于处理JSON数据的C库。它提供了将JSON数据序列化为字符串以及从字符串反序列化为C数据结构的功能。Jsoncpp是开源的&#xf…

Ubuntu20.04安装ROS2教程

Ubuntu20.04安装ROS2教程 ROS 2 安装指南支持的ROS 2 版本设置语言环境&#xff08;Set locale&#xff09;设置源&#xff08;Setup Sources&#xff09;设置密钥安装 ROS 2 包&#xff08;Install ROS 2 packages&#xff09;环境设置&#xff08;Environment setup&#xff…

拟声 0.37.0 | 拟物风格,超级优美,功能丰富

拟声是一款功能丰富的音视频播放器&#xff0c;支持多种音频来源&#xff0c;并具备独特的歌词弹幕、音源转换、跨设备共享与控制等功能。其创新的LRC歌词编解码器和新拟物风格的UI设计为用户提供了一个全新的视听体验。 大小&#xff1a;36M 百度网盘&#xff1a;https://pan…

第三届OpenHarmony技术大会在上海成功举办

10月12日&#xff0c;以“技术引领筑生态&#xff0c;万物智联创未来”为主题的第三届OpenHarmony技术大会&#xff08;以下简称“大会”&#xff09;在上海成功举办。本次大会由OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;项目群技术指导委员会&…

【Mac苹果电脑安装】DBeaverEE for Mac 数据库管理工具软件教程【保姆级教程】

Mac分享吧 文章目录 DBeaverEE 数据库管理工具 软件安装完成&#xff0c;打开效果图片Mac电脑 DBeaverEE 数据库管理工具 软件安装——v24.21️⃣&#xff1a;下载软件2️⃣&#xff1a;安装JDK&#xff0c;根据下图操作步骤提示完成安装3️⃣&#xff1a;安装DBeaverEE&#…

如何进行数据库缩容 | OceanBase应用实践

作者&#xff1a;关炳文&#xff0c;爱可生 DBA 团队成员&#xff0c;负责数据库相关技术支持。 本文详细介绍了OceanBase V3.2版的集群中&#xff0c;面对数据文件缩容的场景的一套缩容方案&#xff0c;作为大家的参考。 缩容场景 某银行运行的一套采用1-1-1架构的OceanBase…

软件架构师 PV

PV操作与生产者消费者问题是操作系统中进程管理和同步机制的重要概念。以下是对PV操作以及生产者消费者问题的详细解释&#xff1a; 一、PV操作 PV操作由P操作原语和V操作原语组成&#xff0c;这两个原语是不可中断的过程&#xff0c;它们对信号量进行操作。 P操作&#xff…

首发 | 数据通解决方案:打造数据工程能力,驱动数据价值转化

数据已经成为企业竞争的核心资源。企业要想从海量数据资源中挖掘数据价值并促进价值转换&#xff0c;需要有全新的工程化方法对数据要素资源进行全生命周期管理。 数据工程是一套完整的实现从数据资源到企业价值的系统工程&#xff0c;旨在通过系统性技术与方法&#xff0c;将…

2024.10.16 软考学习笔记

刷题网站&#xff1a; 软考中级软件设计师在线试题、软考解析及答案-51CTO题库-软考在线做题备考工具

vector简单模拟

1.二维vector 下图可以看到vector<int>指向的是几个int型的&#xff0c;而vector<vector<int>>则指向的是几个vector<int>型的内容&#xff0c;而它们又指向几个int型的内容&#xff0c;三维就重复就可以理解。 例题&#xff1a; 可以得到的规律中间(…

Java—继承性与多态性

目录 一、this关键字 1. 理解this 2. this练习 二、继承性 2.1 继承性的理解 2.1.1 多层继承 2.2 继承性的使用练习 2.2.1 练习1 2.2.2 练习2 2.3 方法的重写 2.4 super关键字 2.4.1 子类对象实例化 三、多态性 3.1 多态性的理解 3.2 向下转型与多态练习 四、Ob…

ArmSoM-Sige7 成为首款支持 openSUSE 的 RK3588 设备

随着嵌入式系统和开源软件的不断发展&#xff0c;越来越多的开发者和爱好者对高性能的开发板及其操作系统支持寄予厚望。在这一背景下&#xff0c;ArmSoM-Sige7 凭借其强大的硬件性能和广泛的软件兼容性&#xff0c;成为了市场的关注焦点。令人兴奋的是&#xff0c;ArmSoM-Sige…

linux 配置ssh免密登录

一、 cd /root/.ssh/ #不存在就创建mkdir /root/.ssh ssh-keygen #连续按4个回车 ll二、将公钥发送到目标服务器下 #公钥上传到目标服务器 ssh-copy-id root192.168.31.142 #回车完也是要输入密码的 #测试一下免密登录&#xff1a; ssh root192.168.31.142 成功

spring如何解决bean循环依赖的问题

1、概述 spring中&#xff0c;存在A依赖B&#xff0c;同时B又依赖A的情况&#xff0c;这种情况下&#xff0c;spring如何进行bean初始化呢&#xff1f; Service public class A {Autowiredprivate B b; }Service public class B {Autowiredprivate A a; } 本文来解释这个问题…

Mindustry像素工厂服务器开服教程

1、购买后登录服务器&#xff08;百度莱卡云游戏面板&#xff09; 进入控制面板后会出现正在安装的界面&#xff0c;大约5分钟左右就能安装完成 2、等待服务器运行起来 等待正常运行时间的表变成灰色之后就可以连接游戏了 3、连接游戏 先复制服务器的地址&#xff0c;单击地址…

【fisco学习记录2】多群组搭建

说明 文档参考&#xff1a; 多群组部署 — FISCO BCOS 2.0 v2.11.0 文档 (fisco-bcos-documentation.readthedocs.io) 多群组搭建之前&#xff0c;先暂停之前的单群组&#xff0c;并删除&#xff1a; cd fisco bash nodes/127.0.0.1/stop_all.sh rm -rf nodes/ 实现图&…

又一款国产自动化测试平台,开源了!

“时间就是金钱&#xff0c;效率就是生命”&#xff0c;在当下的社会里不仅我们的生活节奏变得越来越快&#xff0c;软件研发上线的节奏也是如此。在如此快节奏的软件开发环境中&#xff0c;高质量的软件测试变得尤为重要。 为了提高测试的效率和质量&#xff0c;建设一个强大…

小北的技术博客:探索华为昇腾CANN训练营与AI技术创新——Ascend C算子开发能力认证考试(初级)

前言 哈喽哈喽友友们,这里是zyll~(小北)智慧龙阁的创始人及核心技术开发者。在技术的广阔天地里,我专注于大数据与全栈开发,并致力于成为这一领域的新锐力量。通过智慧龙阁这个平台,我期望能与大家分享我的技术心得,共同探索技术的无限可能。 Ascend C编程:小北的技术…

【大数据技术基础 | 实验二】Linux基础:常用基本命令和文件操作

文章目录 一、实验目的二、实验要求三、实验环境四、常用基本命令1、验证cd和pwd命令2、验证ls命令3、验证mkdir命令4、验证cp、mv和rm命令 五、Linux文件操作1、验证touch命令2、验证cat命令3、验证more命令 六、实验心得 一、实验目的 学会linux常用命令(cd,ls,pwd,mkdir,rm…