内容来源于哔站视频,仅仅作为自己的笔记记录,感兴趣的小伙伴去原作品大call(此处给作者三鞠躬),Json以及Json在Qt中的使用 【Qt/C/C++】_哔哩哔哩_bilibili
目录
2.6.7 QJsonObject和QJsonArray的区别
2.5.1 QJsonArray和QJsonObject->字符串
2.5.2 字符串->QJsonArray和QJsonObject
3.2.2 QJsonArray或者QJsonObject===>字符串
3.3.2 字符串===>QJsonArray或者 QJsonObject
1、Json介绍:
1.1 Json的定义
JSON(JavaScrip Object Notation)是一种轻量级的数据交换格式。它基于ECMAScript(欧洲计算机协会订制的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言。易于人阅读和缩写,同时也易于机器解析和生成,并有效地提升网络传输效率。
简述:Json是一种数据格式,和语言无关,什么语言中都可以使用Json。基于这种通用的数据格式,一般处理两方面的任务:
1.组织数据(数据序列化),用于数据的网络传输。
2.组织数据(数据序列化),写磁盘文件实现数据的持久化存储(一般.json作为作为文件后缀)
(什么时候需要数据持久化到磁盘?记住用户名、密码,简单存储到磁盘文件,通过加载本地配置文件,当窗口显示的时候就会加载配置文件,而不是读取磁盘内容,用户体验会更好。)
1.2 Json的数据格式
Json中主要有两种数据格式:Json数组和Json对象,并且这两种格式可以交叉嵌套使用,下面一次介绍这两种数据格式:
1.2.1 Json数组:
Json数组使用[]表示,[]里边是元素,元素和元素之间使用“,”间隔开,最后一个元素后边没有逗号,一个Json数组中支持同时存在多种不同类型的成员,包括:整型、浮点、字符串、布尔类型、json数组、json对象、空值-null。由此可见Json数组比起c/c++数组灵活很多。
字符串要写到双引号(“”)里边。
Json数组中嵌套Json数组,父子关系
Json数组嵌套Json对象,Json对象可以嵌套Json数组
(1)Json数组中的元素数据类型一致
[1, 2, 3] //整型
["哈哈","hehe","yiyi"] //字符串
(2)Json数组中的元素数据类型不一致
[1, 2, 3, true, false, "haha",null]
(3)Json数组中的数据嵌套使用
[
["cat", "狗狗", "河马", 1]//元素类型可以不一致
[1, 3, 5, true]
]
(4)Json数组和Json对象嵌套
Json对象写入Json数组,数组是父节点,对象是子节点,Json对象下的Json对象是三级节点(Key:value)。"小明"是key值,{}是小明的value值,属性是键值对,
[//外层是Json数组
{//内层是Json对象
"小明":{//属性键值对
"age":19,
"father":"大华",
"sister":"小妹",
"sister1":"大妹" //sister键值不可以重复
}
}
]
1.2.2 Json对象
Json对象使用{}来描述,每个Json对象可以存储若干个元素,每个元素对应一个键值对(key:value),元素和元素之间使用 , 间隔,最后一个元素后面没有 , 注意:
- 键值key,必须是字符串,位于同一层级的键值,不能重复(通过键值取出数据value)
- value值的类型是可选的,整形,浮点型,字符串,json数组,json对象,空值-null(null)
使用Json对象描述一个人的信息:
{
"NAME":"ACE",
"Sex":"man",
"Age":20,
"Family":{
"Father":"yiyi",
"brother":["aa","bb","cc"]
},
"IsLive":"true"
}
小细节:最后一个键值对没有逗号!!!
数据简单放数组,数据更复杂放Json对象,数组和对象的嵌套使用可以更加完整描述模型!!!
(温馨提示:逻辑关系确定清楚哦!!!)
1.2.3 注意事项
- 逗号(“,”)不能乱加,解析会出错。注意最后一个元素不能加逗号,否则解析出错。
- 键值不唯一,不能搜到到正确的value
- 数组持久化的过程中,后缀是".json"不是必须,但是推荐使用".json"
- 数据块只允许有一个根节点
错误示范:
此处存入了两个数据块,存在两个根节点,是不允许的!!!
2、Qt提供的Json类的使用
2.1 Json类介绍
2.1.1 四个常用Json类
2.1.2 四个常用Json类之间的关系
JsonValue包装了Json支持的数据类型,JsonValue相当于一个箱子,可以重载JsonValue得到不同数据类型。
2.2 QJsonValue
2.2.1 封装的数据类型6:
- bool类型 QJsonValue::Bool
- double类型 QJsonValue::Double
- string类型 QJsonVale::String
- array类型 QJsonValue.:Array
- object类型 QJsonValue:Object
- null了下 QJsonValue::Null
2.2.2 通过构造函数,将6种不同的类型统一。
类似于6种类型,放到一个箱子里面。
2.3 QJsonObject
封装了Json中的对象,在里边可以存储多个键值对,为了方便操作,键值为字符串类型,值为QJsonValue类型,关于这个类的使用类似,C++中STL类 QJsonObject内数据使用insert插入,根据key值,自动排序,底层红黑树,升序
2.3.1 创建空的Json对象
QJsonObject::QJsonObject() //构造空对象
2.3.2 将键值对添加到Json对象中
iterator QJsonObject::insert(const QString &key, const QJsonValue &value);//key value
2.3.3 获取对象中,键值对个数
int QJsonObject::count() const;
int QJsonObject::size() const;
int QJsonObject::length() const;
2.3.4 通过key取出value
传入key:得到QJsonObject对象,看看是什么,在使用to方法,得到原始数据
1、QJsonValue QJsonObject:: value(const QString &key) const; //utf-8
2、QJsonValue QJsonObject:: value(QLatin1QString key) const; //字符串不支持中文
3、QJsonValue QJsonObject:: operator[](const QString &key) const; //使用的时候["key值"]
4、QJsonValue QJsonObject:: operator[](QLatin1QString key) const;
2.3.5 删除键值对
void QJsonObject::remove(const QString &key);
QJsonValue QJsonObject::take(const QString &key); //删除键值对后,返回value值
2.3.6 通过key进行查找
iterator QJsonObject::find(const QString &key); //返回的是迭代器,解引用,可以得到数据value值 bool
QJsonObject::contains(const QString &key) const; //查看QJsonObject对象中,是否 存在这个key键值对
2.3.7 遍历方式3种
1.使用迭代器函数
2.使用[],遍历,类似遍历数组,[]中是key
3.先得到对象中所有的键值,在遍历键值列表,通过key得到value QStringList QJsonObject::keys() const;//得到当前Json对象中所有的key值
QStringList QJsonObject::keys() const;//得到当前Json对象中所有的key值
细节+++:QJsonObject在插入时会根据键值对数据升序排序,而QJsonArray不会根据键值排序,所以QJsonObject插入数据顺序完全由键值决定,因此插入顺序和排序顺序可能不同。但QJsonArray在插入数据的时候,数据存储在同一块连续内存中,所以插入顺序就是数据的排序顺序。
2.4 QJsonArray
- QJsonArray里面封装了Json数组,里面存储多个元素,为了方便操作,所有元素类型统一为QJsonValue类型
- 注意:QJsonArray内元素是无序的,完全按照添加顺序存储。
- 先添加,放在前面,后添加放在后面。插入,就放在插入的位置。
2.4.1 创建空的Json数组
QJsonArray::QJsonArray() //得到空的Json数组,通过size()方法,返回值为0
2.4.2 添加数据
void QJsonArray::append(const QJsonValue &value); //在尾部追加
void QJsonArray::insert(int i, const QJsonValue &value); //插入到i的位置之前
iterator QJsonArray::insert(iterator before, const QJsonValue &value); //在迭代器当前位置的前面,插入
void QJsonArray::prepend(const QJsonValue &value); //添加到数组头部
void QJsonArray::push_back(const QJsonValue &value); //添加到尾部
void QJsonArray::push_front(const QJsonValue &value); //添加到头部
2.4.3 计算数组内元素的个数
int QJsonArray::count() const;
int QJsonArray::size() const;
2.4.4 从数组中取出某一个元素的值
QJsonValue QJsonArray::at(int i) const; //参数i:为在数组中元素对应的下标 拷贝,不能修改数组内元素的值
QJsonValue QJsonArray::first() const; //头部元素 拷贝
QJsonValue QJsonArray::last() const; //尾部元素 拷贝
QJsonValueRef QJsonArray::operator[](int i);//这里返回的值是引用,可以修改 数组内的值
2.4.5 从数组中删除某一个元素的值
iterator QJsonArray::erase(iterator it); //基于迭代器的删除
void QJsonArray::pop_back(); //删除尾部
void QJsonArray::pop_front(); //删除头部
void QJsonArray::removeAt(int i); //删除i位置元素
void QJsonArray::removeFirst(); //删除头部
void QJsonArray::removeLast(); //删除尾部
QJsonValue QJsonArray::takeAt(int i); //删除i位置的原始,并返回删除元素的值
2.4.6 遍历
1、使用迭代器遍历(和使用迭代器遍历STL容器一样)
2、使用数组方式遍历
总结:通过[]或者takeAt方法得到返回值为QJsonValue类型,通过返回数据QJsonValue类型进行判断,然后调用“to”方法得到原始数据。取出的原始元素,不是我们需要的数据类型,需要"to方法"进行换行。
2.6.7 QJsonObject和QJsonArray的区别
QJsonObject是用于表示JSON对象的类,它类似于C++中的std::map或字典数据结构,可以使用键值对存储和访问数据。每个键都是唯一的,与每个值关联。QJsonObject内部以键值对的形式组织数据,其中键是字符串,值可以是字符串、数字、布尔值、其他JSON对象或JSON数组。
QJsonArray是用于表示JSON数组的类,它类似于C++中的std::vector或列表数据结构,可以按照索引顺序存储和访问数据。QJsonArray可以包含多个元素,每个元素可以是字符串、数字、布尔值、其他JSON对象或JSON数组。
区别总结如下:
- QJsonObject用于表示JSON对象,通过键值对存储和访问数据。
- QJsonArray用于表示JSON数组,按照索引顺序存储和访问数据。
在处理复杂的JSON数据时,QJsonObject和QJsonArray经常会一起使用。例如,一个JSON对象的值可以是一个JSON数组,而一个JSON数组的元素也可以是JSON对象。这样的结构可以通过嵌套使用QJsonObject和QJsonArray来表示。
请注意,在使用QJsonObject和QJsonArray之前,你需要包含相应的头文件#include <QJsonObject>
和#include <QJsonArray>
,并链接到QtCore模块。
2.5 QJSonDocument
它封住了一个完整的Json文档,并且可以从UTF-8编码的基于文本的表示以及Qt自己的二进制格式读取和写入该文档。 QJsonObject和QJsonArray这两个对象中的数据是不能直接转换为字符串类型的, 如果要进行数据传输或者数据的持久化,操作的都是字符串类型,不是QJsonArray或者QjsonObject类型, 需要使用JsonDocument进行二者之间的转换。
2.5.1 QJsonArray和QJsonObject->字符串
- QJsonDocument(const QJsonDocument &other):移动构造 右值引用 不可取地址的数据
- QJsonDocument(QJsonDocument &&other):拷贝构造 左值引用 可取地址数组
- void setArray(const QJsonArray &array):设置空QJsonDocument对象
- void setObject(const QJsonObject &object):设置空QJsonDocument对象
- void swap(QJsonDocument &other):交换两个QJsonDocument对象
将QJsonDocument对象转换为字符串QByteArray
QByteArray toJson(QJsonDocument::JsonFormat format) const
- 创建一个QJsonObject,并添加了一些键值对。
- 我们使用toJson将QJsonObject转换为QByteArray
- 我们将QByteArray转换为std::string,并打印出来。
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>
QJsonObject jsonObject;
jsonObject["key1"] = "value1";
jsonObject["key2"] = 42;
QJsonDocument jsonDocument(jsonObject);
QByteArray byteArray = jsonDocument.toJson();
std::string jsonString = byteArray.toStdString();
qDebug() << "JSON String:" << jsonString.c_str();
也可以将QByteArray转换为QString,而不是std::string。例如,可以使用QString::fromUtf8()
函数将字节数组转换为QString。
请注意,在使用QJsonDocument之前,你需要包含了#include <QJsonDocument>
头文件,并链接到QtCore模块。
2.5.2 字符串->QJsonArray和QJsonObject
将字符串QByteArray 转换为QJsonDocument 对象
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = nullptr)//第一个参数传入字符串,返回QJsonDocument 对象
- 创建一个包含JSON数据格式的字符串jsonString
- 将字符串转换为QByteArray
- fromJson()将函数解析为QJsonDocument对象
- isObject()判断是否为有效JSON对象,是则转换为QJsonObject对象
- 通过键来获取QJsonObject中的值。
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>
QString jsonString = "{\"key1\":\"value1\", \"key2\":42}";
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8());
if (!jsonDocument.isNull()) {
if (jsonDocument.isObject()) {
QJsonObject jsonObject = jsonDocument.object();
QString value1 = jsonObject["key1"].toString();
int value2 = jsonObject["key2"].toInt();
qDebug() << "key1:" << value1;
qDebug() << "key2:" << value2;
}
}
3 Json文件操作的例子
3.1 主要运用技术方法
- Json文件的序列化和反序列化
- QFile文件操作
- QJsonDocument、QJsonArray、QJsonObject、QJsonArray
Json数据内容
数据有三层嵌套,对象"{}"套对象"{}",对象"{}"套数组"[]"
//test.json
//Json描述一个人的信息:
{
"NAME":"ACE",
"Sex":"man",
"Age":20,
"Family":{
"Father":"Babi",
"Mother":"MaMi",
"brother":["aa","bb","cc"]
},
"IsLive":"true",
"Comment":'yyds'
}
3.2 Json文件序列化:writeJson函数代码实现
3.2.1 序列化
- 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。对象的状态(包括属性、数据)被转换为字节流或其他表示形式,以便可以在不同的环境中传输、存储或重建对象。序列化可以将对象转换为平台无关的格式,使得可以在不同的编程语言和平台之间进行对象的交互和传输。
此处的序列化指:将QJsonObject 通过QJsonDocument转换为 QByteArray(即文本格式字符串) QJSonObject/QJsonArray===>字符串
- 序列化的主要目的有以下几点:
持久化对象:将对象保存到文件系统或数据库中,以便在以后重新加载和使用。
对象传输:将对象通过网络传输给其他系统或进程。
远程过程调用(RPC):通过将对象序列化为消息,实现跨网络调用远程方法。
对象复制:通过将对象序列化为字节流,实现对象的复制和克隆。
- 在序列化过程中,对象的状态通常包括其属性值、字段值和关联的对象等信息。
- 一些常见的序列化格式包括JSON(JavaScript Object Notation)、XML(eXtensible Markup Language)、Protocol Buffers等。
3.2.2 QJsonArray或者QJsonObject===>字符串
- 创建QJsonDocument对象
QJsonDocument::QJsonDocument(const QJsonObject &object);
QJsonDocument::QJsonDocument(const QJsonArray &array);
通过构造函数将示例化后的QJsonObject 或者 QJsonArray转换为QJsonDocument对象
- 将文件对象中的数据进行序列化
QByteArray QJsonDocument::toJson(QJsonDocument::JsonFormat format) const//文本格式
QByteArray QJsonDocument::toBinaryData() const//二进制格式
通过调用toXXX()方法可以将QJsonDocument对象转换为文本格式或者二进制格式的Json字符串
- 使用得到的字符串进行数据传输或者磁盘文件存储
- writeJson函数:
void MainWindow::writeJson()
{
//Json对象数据组织
QJsonObject obj;
obj.insert("name","ACE");
obj.insert("sex","man");
obj.insert("age",20);
QJsonObject subObj;
obj.insert("father","Babi");
obj.insert("mother","Mami");
QJsonArray array;
array.append("aa");
array.append("bb");
array.append("cc");
obj.insert("brother",array);
obj.insert("family",subObj);
obj.insert("islive","true");
obj.insert("comment","yyds");//Json数据组织
QJsonDocument doc(obj);//第一步 建立QJsonDocument对象
QByteArray json = doc.toJson();//第二步 QJsonDocument对象的数据转文本格式json字符串
QFile file("./test.json");//第三步 字符串存储到计算机磁盘
if(file.open(QFile::WriteOnly))
{
file.write(json);
}
file.close();
}
- 运行后test.json结果:因为按照键值排序,键值为英文字母所以 排序是英文字母ASCII码的排序。因此和输入程序的顺序明显不同!使用QJsonObject会导致和程序输入顺序不同!!!
3.3 Json文件反序列化:readJson函数实现
3.3.1 反序列
- 反序列化(Deserialization)是将序列化后的数据转换回原始对象的状态的过程。
- 在计算机科学和软件开发中,反序列化用于从序列化的表示形式中恢复对象的状态,以便能够使用、操作和处理对象的数据。
- 在反序列化过程中,序列化的数据(如字节流、JSON字符串、XML文档等)被解析和转换为对象的状态,包括属性、字段和关联的对象等信息,可以将数据重新还原为原始的对象形式,以便进一步使用和操作。
- 具体的反序列化过程取决于所使用的序列化格式和编程语言。常见的序列化格式如JSON、XML和Protocol Buffers都有相应的反序列化机制。
3.3.2 字符串===>QJsonArray或者 QJsonObject
- 将得到的Json格式字符串通过QJsonDocument类的静态函数转换为QJsonDocument类对象
[static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = nullptr)//参数为文件格式的字符串
[static] QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, QJsonDocument::DataValidation validation = Validate)//参数为二进制格式
- 将文本对象转换为json数组/对象
//判断文档对象中存储的数据是不是json数组
bool QJsonDocument::isArray() const
//判断文档对象中存储的数据是不是json对象
bool QJsonDocument::isObject() const
//文档对象中的数据转换为json对象
QJsonObject QJsonDocument::object() const
//文档对象中的数据转换为json数组
QJsonObject QJsonDocument::array() const
- 通过调用QJsonQrray或者QJsonObject类提供的API读取存储在对象中的数据
- readJson函数实现
void MainWindow::readJson()
{
QFile file("./test.json");
if(file.open(QFile::ReadOnly))
{
QByteArray all = file.readAll();
QJsonDocument doc = QJsonDocument::fromJson(all);
if(doc.isObject())
{
QJsonObject obj = doc.object();
QStringList keys = obj.keys();
for(int i=0;i<keys.size();++i)
{
QString key =keys.at(i);
QJsonValue value = obj.value(key);
if(value.isBool())
{
qDebug()<<key<<":"<<value.toBool();
}
else if(value.isString())
{
qDebug()<<key<<":"<<value.toString();
}
else if(value.isDouble())
{
qDebug()<<key<<":"<<value.toInt();
}
else if(value.isObject())
{
qDebug()<<key<<":";
QJsonObject subObj = value.toObject();
QStringList subKeys = subObj.keys();
for(int k=0;k<subKeys.size();++k)
{
QJsonValue subValue = subObj.value(subKeys.at(k));
if(subValue.isString())
{
qDebug()<<" "<<subKeys.at(k)<<":"<<subValue.toString();
}
else if(subValue.isArray())
{
qDebug()<<" "<<subKeys.at(k)<<":";
QJsonArray array = subValue.toArray();
for(int m=0;m<array.size();++m)
{
qDebug()<<" "<<array[m].toString();
}
}
}
}
}
}
}
file.close();
}
3.4 整体代码
3.4.1 mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void writeJson();
void readJson();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
3.4.2 mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QJsonDocument>
#include<QJsonObject>
#include<QJsonArray>
#include<QJsonValue>
#include<QDebug>
#include<QFile>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QJsonDocument doc;
if(doc.isEmpty())
{
qDebug()<<"Json document is empty...";
}
if(doc.isNull())
{
qDebug()<<"Json document is null...";
}
writeJson();
readJson();
}
MainWindow::~MainWindow()
{
delete ui;
}
/*
//test.json
//Json描述一个人的信息:
{
"NAME":"ACE",
"Sex":"man",
"Age":20,
"Family":{
"Father":"Babi",
"Mother":"MaMi",
"brother":["aa","bb","cc"]
},
"IsLive":"true",
"Comment":'yyds'
}
*/
void MainWindow::writeJson()
{
//Json对象数据组织
QJsonObject obj;
obj.insert("name","ACE");
obj.insert("sex","man");
obj.insert("age",20);
QJsonObject subObj;
subObj.insert("father","Babi");
subObj.insert("mother","Mami");
QJsonArray array;
array.append("aa");
array.append("bb");
array.append("cc");
subObj.insert("brother",array);
obj.insert("family",subObj);
obj.insert("islive","true");
obj.insert("comment","yyds");//Json数据组织
QJsonDocument doc(obj);
QByteArray json = doc.toJson();//json数据转文本格式字符串
QFile file("./test.json");
if(file.open(QFile::WriteOnly))
{
file.write(json);
}
file.close();
}
void MainWindow::readJson()
{
QFile file("./test.json");
if(file.open(QFile::ReadOnly))
{
QByteArray all = file.readAll();
QJsonDocument doc = QJsonDocument::fromJson(all);
if(doc.isObject())
{
QJsonObject obj = doc.object();
QStringList keys = obj.keys();
for(int i=0;i<keys.size();++i)
{
QString key =keys.at(i);
QJsonValue value = obj.value(key);
if(value.isBool())
{
qDebug()<<key<<":"<<value.toBool();
}
else if(value.isString())
{
qDebug()<<key<<":"<<value.toString();
}
else if(value.isDouble())
{
qDebug()<<key<<":"<<value.toInt();
}
else if(value.isObject())
{
qDebug()<<key<<":";
QJsonObject subObj = value.toObject();
QStringList subKeys = subObj.keys();
for(int k=0;k<subKeys.size();++k)
{
QJsonValue subValue = subObj.value(subKeys.at(k));
if(subValue.isString())
{
qDebug()<<" "<<subKeys.at(k)<<":"<<subValue.toString();
}
else if(subValue.isArray())
{
qDebug()<<" "<<subKeys.at(k)<<":";
QJsonArray array = subValue.toArray();
for(int m=0;m<array.size();++m)
{
qDebug()<<" "<<array[m].toString();
}
}
}
}
}
}
}
file.close();
}