Qt JSON详解一

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对象中



2.3.3 获取对象中,键值对个数



2.3.4 通过key取出value


传入key:得到QJsonObject对象,看看是什么,在使用to方法,得到原始数据


2.3.5 删除键值对


void QJsonObject::remove(const QString &key);
QJsonValue QJsonObject::take(const QString &key); //删除键值对后,返回value值


2.3.6 通过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 添加数据


2.4.3 计算数组内元素的个数


int QJsonArray::count() const; 
int QJsonArray::size() const;


2.4.4 从数组中取出某一个元素的值


2.4.5 从数组中删除某一个元素的值


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数组/对象


通过调用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();
}
 

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高亚奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值