Qt构建JSON及解析JSON

news2024/9/20 3:22:31

目录

一.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(); // 读取文件内容到QByteArray
    QJsonDocument doc = QJsonDocument::fromJson(Bit); // 将QByteArray解析为QJsonDocument

    if (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.coloradmin.cn/o/2143712.html

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

相关文章

详解:Tensorflow、Pytorch、Keras(搭建自己的深度学习网络)

这是一个专门对Tensorflow、Pytorch、Keras三个主流DL框架的一个详解和对比分析 一、何为深度学习框架&#xff1f; 你可以理解为一个工具帮你构建一个深度学习网络&#xff0c;调用里面的各种方法就能自行构建任意层&#xff0c;diy你想要的DNN&#xff0c;而且任意指定学习…

揭秘!当业务方需求模糊,产品经理如何施展‘化雾为金’的神奇策略!

引言 在产品管理的实践中&#xff0c;产品经理经常会遇到业务方无法清晰表达需求的情况。这可能是由于业务方对问题的理解不够深入&#xff0c;或者缺乏将业务需求转化为产品需求的经验。作为资深产品经理&#xff0c;我们需要采取一系列策略来应对这一挑战&#xff0c;确保产…

Solid Converter PDF9.1安装教程

软件介绍 Solid Converter PDF是一套专门将PDF文件转换成word的软件&#xff0c;除了转换成word文件外&#xff0c;还可以转换成RTF以及Word XML文件。除此之外&#xff0c;它还有一个图片撷取功能&#xff0c;可以让我们]将PDF档里的图片撷取出来&#xff0c;以及将PDF档里的…

word文档的读入(8)

如何读取答题卡中的选择题答案&#xff0c;并把所有的信息导入到Excel表格中&#xff5e; 在初始化了字典中的字段并获取了标准答案和学生答案后&#xff0c;现在只需使用if语句将学生答案studentAnswerOne和标准答案value进行比较。选择题一道题2分&#xff0c;答案正确时&…

C++11 右值引用完美转发

前言 上一期介绍了C11的基础新特性&#xff0c;这一期开始我们继续来介绍C11的新特性&#xff01; 目录 前言 一、右值引用和移动语义 1.1左值和左值引用 1.2右值和右值引用 1.3左值引用vs右值引用 1.4右值引用的使用场景和意义 左值引用的使用场景 左值引用的缺陷 …

应用案例|开源 PolarDB-X 在互联网安全场景的应用实践

背景介绍 中盾数科集团始创于2012年&#xff0c;是由网络安全服务而发展起来的科技型、多元化的企业集团。旗下包括网络安全服务、信创一体化服务、箱式液冷、区块链、位置服务、视觉服务等六大板块&#xff0c;业务覆盖湖南、甘肃、贵州等多个省份。 业务挑战 中盾集团基于A…

LabVIEW提高开发效率技巧----模块化设计与代码复用

模块化设计是现代软件开发中不可或缺的理念&#xff0c;在LabVIEW开发中尤为重要。通过将系统功能划分为独立的、可复用的模块&#xff0c;开发者可以显著提升代码的可读性、维护性以及效率。下面将介绍模块化设计的核心概念、如何利用子VI实现代码复用、以及使用模板&#xff…

claude,gpt,通义千问

起因是通义千问对这张图的解释有严重错误&#xff0c;因此想着让claude和gpt回答一下&#xff0c;记录一下。 claude 这张图表显示了中国多个城市的房地产价格指数数据。让我为您解读一下主要信息&#xff1a; 指标解释&#xff1a; "环比": 与上月相比的价格变化&…

[yotroy.cool] MGT 388 - Finance for Engineers - notes 笔记

个人博客https://www.yotroy.cool/,感谢关注~ 图片资源可能显示不全,请前往博客查看哦! ============================================================ Lecture 1 What is Accounting? The process of identifying, measuring and communicating economic informati…

【UEFI基础】BIOS下的启动项管理

启动管理 启动管理&#xff08;Boot Manager&#xff09;是UEFI BIOS中重要的一部分&#xff0c;它通过一系列的变量来确定启动策略&#xff0c;包括&#xff1a; 执行启动还是恢复操作启动顺序是如何 本文会介绍下面的内容&#xff1a; 与启动管理相关的变量启动或恢复的流…

Git rebase 的使用(结合图与案例)

目录 Git rebase 的使用Git rebase 概念Git rebase 原理rebase和merge的选择 Git rebase 的使用 在 Git 中整合来自不同分支的修改主要有两种方法&#xff1a;merge 以及 rebase Git rebase 概念 **rebase概念&#xff1a;**用来重新应用提交&#xff08;commits&#xff09…

Vue2知识点

注意:笔记内容来自网络 1Vue指令 指令是指&#xff1a;带有v-前缀的特殊标签属性 1.1 v-html v-html&#xff08;类似 innerHTML&#xff09; 使用语法&#xff1a;<p v-html"intro">hello</p>&#xff0c;意思是将 intro 值渲染到 p 标签中 类似 i…

神经网络-MNIST数据集训练

文章目录 一、MNIST数据集1.数据集概述2.数据集组成3.文件结构4.数据特点 二、代码实现1.数据加载与预处理2. 模型定义3. 训练和测试函数4.训练和测试结果 三、总结 一、MNIST数据集 MNIST数据集是深度学习和计算机视觉领域非常经典且基础的数据集&#xff0c;它包含了大量的手…

链表的合并,结点逆置,顺序表的高效划分(数据结构作业02)

目录 链表的合并 链表的结点逆置 顺序表的高效划分 链表的合并 已知两个递增有序的单链表A和B&#xff0c;分别表示两个集合。试设计一个算法&#xff0c;用于求出A与B的交集&#xff0c;并存储在C链表中。例如 : La {2&#xff0c;4&#xff0c;6&#xff0c;8}&#xff1b;…

闯关leetcode——28. Find the Index of the First Occurrence in a String

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/description/ 内容 Given two strings needle and haystack, return the index of the first occurrence of needle in haystack, or -1 if …

冒泡排序的C++语言实现(不用std::sort)

自己写一个冒泡排序的代码。 void vSort(std::vector<int> & vec, bool bDescending) {//冒泡排序int iTail vec.size()-1;while(iTail > 0){for(int k 0; k < iTail; k){int f1 vec.at(k);int f2 vec.at(k1);if(f1 < f2){//默认是降序int iTmp vec.a…

为什么大公司不用pandas取代excel?

如果你熟练使用Excel的话&#xff0c;你就会发现有些pandas的功能&#xff0c;在Excel中也可以实现&#xff0c;而且对比下来&#xff0c;Excel操作更简单&#xff0c;从效率上跟pandas更无二致&#xff0c;这样Excel的优势就比较突出了&#xff0c;比如下面使用pandas和Excel分…

【实战篇】幻读是什么,幻读有什么问题?

背景 我们先使用一个小一点儿的表。建表和初始化语句如下&#xff1a; CREATE TABLE t (id int(11) NOT NULL,c int(11) DEFAULT NULL,d int(11) DEFAULT NULL,PRIMARY KEY (id),KEY c (c) ) ENGINEInnoDB; insert into t values(0,0,0),(5,5,5), (10,10,10),(15,15,15),(20,…

2010-2022 CSP-J/普及组T1-T4考点统计

T1考点统计 T2考点统计 T3考点统计 T4考点统计 总结

MOE论文汇总2

TASK-CUSTOMIZED MASKED AUTOENCODER VIA MIXTURE OF CLUSTER-CONDITIONAL Experts 这篇论文提出了一种新颖的自监督学习方法&#xff0c;名为“Mixture of Cluster-conditional Experts (MoCE)”&#xff0c;旨在解决传统Masked Autoencoder (MAE)在不同下游任务中可能遇到的负…