参考博客:

之前介绍了许多 C++ 的 Json 第三方库,

下面介绍一下 Json 在 Qt 中的使用。

从Qt 5.0开始提供了对 Json 的支持,我们可以直接使用Qt提供的 Json 类进行数据的组织和解析。相关的类常用的主要有四个,具体如下:

Json类 介绍
QJsonDocument 它封装了一个完整的JSON文档,并且可以从UTF-8编码的基于文本的表示以及Qt自己的二进制格式读取和写入该文档。
QJsonArray JSON数组是一个值列表。可以通过从数组中插入和删除QJsonValue来操作该列表。
QJsonObject JSON对象是键值对的列表,其中键是唯一的字符串,值由QJsonValue表示。
QJsonValue 该类封装了JSON支持的数据类型。

一、QJsonValue

在Qt中 QJsonValue 可以封装的基础数据类型有六种(和Json支持的类型一致),分别为:

  • 布尔类型:QJsonValue::Bool
  • 浮点类型(包括整形):QJsonValue::Double
  • 字符串类型: QJsonValue::String
  • Json数组类型: QJsonValue::Array
  • Json对象类型:QJsonValue::Object
  • 空值类型: QJsonValue::Null

这个类型可以通过 QJsonValue 的构造函数被封装为一个类对象:

// Json对象
QJsonValue(const QJsonObject &o);
// Json数组
QJsonValue(const QJsonArray &a);
// 字符串
QJsonValue(const char *s);
QJsonValue(QLatin1String s);
QJsonValue(const QString &s);
// 整形 and 浮点型
QJsonValue(qint64 v);
QJsonValue(int v);
QJsonValue(double v);
// 布尔类型
QJsonValue(bool b);
// 空值类型
QJsonValue(QJsonValue::Type type = Null);

如果我们得到一个 QJsonValue 对象,如何判断内部封装的到底是什么类型的数据呢?这时候就需要调用相关的判断函数了,具体如下:

// 是否是Json数组
bool isArray() const;
// 是否是Json对象
bool isObject() const;
// 是否是布尔类型
bool isBool() const;
// 是否是浮点类型(整形也是通过该函数判断)
bool isDouble() const;
// 是否是空值类型
bool isNull() const;
// 是否是字符串类型
bool isString() const;
// 是否是未定义类型(无法识别的类型)
bool isUndefined() const;

通过判断函数得到对象内部数据的实际类型之后,如果有需求就可以再次将其转换为对应的基础数据类型,对应的API函数如下:

// 转换为Json数组
QJsonArray toArray(const QJsonArray &defaultValue) const;
QJsonArray toArray() const;
// 转换为布尔类型
bool toBool(bool defaultValue = false) const;
// 转换为浮点类型
double toDouble(double defaultValue = 0) const;
// 转换为整形
int toInt(int defaultValue = 0) const;
// 转换为Json对象
QJsonObject toObject(const QJsonObject &defaultValue) const;
QJsonObject toObject() const;
// 转换为字符串类型
QString toString() const;
QString toString(const QString &defaultValue) const;

二、QJsonObject

QJsonObject 封装了Json中的对象,在里边可以存储多个键值对,为了方便操作,键值为字符串类型,值为QJsonValue 类型。

关于这个类的使用类似于C++中的STL类,仔细阅读API文档即可熟练上手使用,下面介绍一些常用API函数:

  • 如何创建空的Json对象

    QJsonObject::QJsonObject();	// 构造空对象
  • 将键值对添加到空对象中

    iterator QJsonObject::insert(const QString &key, const QJsonValue &value);
  • 获取对象中键值对个数

    int QJsonObject::count() const;
    int QJsonObject::size() const;
    int QJsonObject::length() const;
  • 通过key得到value

    QJsonValue QJsonObject::value(const QString &key) const;    // utf8
    QJsonValue QJsonObject::value(QLatin1String key) const; // 字符串不支持中文
    QJsonValue QJsonObject::operator[](const QString &key) const;
    QJsonValue QJsonObject::operator[](QLatin1String key) const;
  • 删除键值对

    void QJsonObject::remove(const QString &key);
    QJsonValue QJsonObject::take(const QString &key); // 返回key对应的value值
  • 通过key进行查找

    iterator QJsonObject::find(const QString &key);
    bool QJsonObject::contains(const QString &key) const;
  • 遍历,方式有三种:

    • 使用相关的迭代器函数

    • 使用 [] 的方式遍历, 类似于遍历数组, []中是键值

    • 先得到对象中所有的键值, 在遍历键值列表, 通过key得到value值

      QStringList QJsonObject::keys() const;

三、QJsonArray

QJsonArray 封装了Json中的数组,在里边可以存储多个元素,为了方便操作,所有的元素类统一为 QJsonValue 类型。关于这个类的使用类似于C++中的STL类,仔细阅读API文档即可熟练上手使用,下面介绍一些常用API函数:

  • 创建空的Json数组

    QJsonArray::QJsonArray();
  • 添加数据

    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); // 添加到头部
  • 计算数组元素的个数

    int QJsonArray::count() const;
    int QJsonArray::size() const;
  • 从数组中取出某一个元素的值

    QJsonValue QJsonArray::at(int i) const;
    QJsonValue QJsonArray::first() const; // 头部元素
    QJsonValue QJsonArray::last() const; // 尾部元素
    QJsonValueRef QJsonArray::operator[](int i);
  • 删除数组中的某一个元素

    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位置的原始, 并返回删除的元素的值
  • Json 数组的遍历,常用的方式有两种:

    • 可以使用迭代器进行遍历(和使用迭代器遍历STL容器一样)
    • 可以使用数组的方式遍历

四、QJsonDocument

它封装了一个完整的JSON文档,并且可以从 \(UTF-8\) 编码的基于文本的表示以及Qt自己的二进制格式读取和写入该文档。

QJsonObjectQJsonArray 这两个对象中的数据是不能直接转换为字符串类型的,如果要进行数据传输或者数据的持久化,操作的都是字符串类型而不是 QJsonObject 或者 QJsonArray 类型,我们需要通过一个Json文档类进行二者之间的转换。

下面依次介绍一下这两个转换流程应该如何操作:

  • QJsonObject 或者 QJsonArray ===> 字符串

    1. 创建 QJsonDocument 对象

      QJsonDocument::QJsonDocument(const QJsonObject &object);
      QJsonDocument::QJsonDocument(const QJsonArray &array);

      可以看出,通过构造函数就可以将实例化之后的 **QJsonObject 或者 QJsonArray **转换为QJsonDocument 对象了。

    2. 将文件对象中的数据进行序列化

      // 二进制格式的json字符串
      QByteArray QJsonDocument::toBinaryData() const;
      // 文本格式
      QByteArray QJsonDocument::toJson(JsonFormat format = Indented) const;

      通过调用 toxxx() 方法就可以得到文本格式或者二进制格式的 Json 字符串了。

    3. 使用得到的字符串进行数据传输, 或者磁盘文件持久化

  • 字符串 ===> QJsonObject 或者 QJsonArray

    一般情况下,通过网络通信或者读磁盘文件就会得到一个Json格式的字符串,如果想要得到相关的原始数据就需要对字符串中的数据进行解析,具体解析流程如下:

    1. 将得到的 Json 格式字符串通过 QJsonDocument 类的静态函数转换为 QJsonDocument 类对象

      [static] QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation = Validate);
      // 参数文件格式的json字符串
      [static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR);
    2. 将文档对象转换为json数组/对象

      // 判断文档对象中存储的数据是不是数组
      bool QJsonDocument::isArray() const;
      // 判断文档对象中存储的数据是不是json对象
      bool QJsonDocument::isObject() const // 文档对象中的数据转换为json对象
      QJsonObject QJsonDocument::object() const;
      // 文档对象中的数据转换为json数组
      QJsonArray QJsonDocument::array() const;
    3. 通过调用QJsonArray , QJsonObject 类提供的 API 读出存储在对象中的数据。

    关于Qt中Json数据对象以及字符串之间的转换的操作流程是固定的,我们在编码过程中只需要按照上述模板处理即可,相关的操作是没有太多的技术含量可言的。

五、Example

5.1 Write to File

void writeJson()
{
QJsonObject obj;
obj.insert("Name", "Ace");
obj.insert("Sex", "man");
obj.insert("Age", 20); QJsonObject subObj;
subObj.insert("Father", "Gol·D·Roger");
subObj.insert("Mother", "Portgas·D·Rouge");
QJsonArray array;
array.append("Sabo");
array.append("Monkey D. Luffy");
subObj.insert("Brother", array);
obj.insert("Family", subObj);
obj.insert("IsAlive", false);
obj.insert("Comment", "yyds"); QJsonDocument doc(obj);
QByteArray json = doc.toJson(); QFile file("d:\\ace.json");
file.open(QFile::WriteOnly);
file.write(json);
file.close();
}

5.2 Read from File

void MainWindow::readJson()
{
QFile file("d:\\ace.json");
file.open(QFile::ReadOnly);
QByteArray json = file.readAll();
file.close(); QJsonDocument doc = QJsonDocument::fromJson(json);
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();
}
if(value.isString())
{
qDebug() << key << ":" << value.toString();
}
if(value.isDouble())
{
qDebug() << key << ":" << value.toInt();
}
if(value.isObject())
{
qDebug()<< key << ":";
// 直接处理内部键值对, 不再进行类型判断的演示
QJsonObject subObj = value.toObject();
QStringList ls = subObj.keys();
for(int i=0; i<ls.size(); ++i)
{
QJsonValue subVal = subObj.value(ls.at(i));
if(subVal.isString())
{
qDebug() << " " << ls.at(i) << ":" << subVal.toString();
}
if(subVal.isArray())
{
QJsonArray array = subVal.toArray();
qDebug() << " " << ls.at(i) << ":";
for(int j=0; j<array.size(); ++j)
{
// 因为知道数组内部全部为字符串, 不再对元素类型进行判断
qDebug() << " " << array[j].toString();
}
}
}
}
}
}
}

一般情况下,对于Json字符串的解析函数都是有针对性的,因为需求不同设计的Json格式就会有所不同,所以不要试图写出一个通用的Json解析函数,这样只会使函数变得臃肿而且不易于维护,每个Json格式对应一个相应的解析函数即可。

上面的例子中为了给大家演示Qt中Json类相关API函数的使用将解析步骤写的复杂了,因为在解析的时候我们是知道Json对象中的所有key值的,可以直接通过key值将对应的value值取出来,因此上面程序中的一些判断和循环其实是可以省去的。

【库函数】Qt中Json的操作的更多相关文章

  1. 第32课 Qt中的文件操作

    1. Qt的中IO操作 (1)Qt中IO操作的处理方式 ①Qt通过统一的接口简化了文件和外部设备的操作方式 ②Qt中的文件被看作一种特殊的外部设备 ③Qt中的文件操作与外部设备的操作相同 (2)IO操 ...

  2. Qt 中QString 字符串操作:连接、组合、替换、去掉空白字符

    Qt中的字符串类 QString类 保存了16位Unicode值,提供了丰富的操作.查询和转换等函数. QString 字符串有如下几个操作符: (1) "+" 用于组合两个字符串 ...

  3. Qt中的打印操作

    Qt中对打印的支持是有一个独立的printsupport模块来完成的,所以,要想在程序中使用Qt的打印功能,必须先在pro文件中添加下面这句代码: QT += printsupport在这个模块中,提 ...

  4. python中json的操作示例

    先上一段示例 # -*- coding: cp936 -*- import json #构造一个示例数据,并打印成易读样式 j = {} j["userName"]="a ...

  5. 1.关于QT中json数据处理和密码md5加密

     新建一个Qt空项目 17Json.pro HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += widgets gui MyWidget ...

  6. JS 中Json常用操作

    转自: https://www.jianshu.com/p/6501b0f3124f 直接定义json var json = {"name": "小明", &q ...

  7. 4.QT中进程操作,线程操作

     QT中的线程操作 T19Process.pro SOURCES += \ main.cpp CONFIG += C++11 main.cpp #include <QCoreApplicat ...

  8. kbmmw 中JSON 操作入门

    现在各种系统中JSON 用的越来越多.delphi 也自身支持JSON 处理. 今天简要说一下kbmmw 内部如何使用和操作JSON. kbmmw 中json的操作是以TkbmMWJSONStream ...

  9. qt中的拖拽及其使用技巧

    关于qt中的拖放操作,首先可以看这篇官方文档:http://doc.qt.io/qt-5.5/dnd.html 一.QDrag 首先是创建QDrag,可以在mousePressEvent或者mouse ...

  10. Qt中如何禁掉所有UI操作以及注意事项(处理各个widget的eventFilter这一层,但是感觉不好,为什么不使用QApplication呢)

    刚做完的一个项目,在测试时出现了一个问题:由于多线程的存在,当进行语音识别时:如果用户点击程序界面上的button或者其他接受点击事件后会发出信号的widget时,程序会crash ! 后来尝试着从多 ...

随机推荐

  1. Dart 初探 (一)

    前言 Dart 是 Google 为 Flutter 开发的一款用于网页编程的语言,其类似于Javascript,也是一种面向对象的语言,但其采用基于类的编程,语法风格接近C语言. 虽说它是开发用于网 ...

  2. [ABP] PostgreSQL在.NET 6.0使用DateTime类型抛出异常:timestamp with time zone

    今晚操起久违的 ABP 框架搭了个新项目: .NET 运行时版本:6.0.3 ABP 版本:v5.2.0-rc.2 版本. 数据库:PostgreSQL v10.x 一顿操作猛如虎,直接用 dotne ...

  3. python之递归(斐波那契数列)与迭代

    对于较大的计算来说,迭代不如递归计算速度快,并且可以说非常慢 但是迭代对于较小的运算又比递归巧妙 # 迭代方法 def slowsnail(x): am = [1, 1] if x < 0: p ...

  4. 使用C#将几个Excel文件合并去重分类

    需要将几个Excel表格里面的数据去重,然后将每个站点的数据另存为一张Sheet上. 几个表格如下所示: 实现效果如下所示: 具体实现 需要使用EPPlus操作Excel 安装EPPlus如下所示: ...

  5. 从管易云到MySQL通过接口配置打通数据

    从管易云到MySQL通过接口配置打通数据 数据源平台:管易云 管易云是金蝶旗下专注提供电商企业管理软件服务的子品牌,先后开发了C-ERP.EC-OMS.EC-WMS.E店管家.BBC.B2B.B2C商 ...

  6. 深入解析C# List<T>的源码

    前面的文章中解释了Array的初始化和元素插入,以及数组整体的存储结构(<深度分析C#中Array的存储结构>).这里我们再来详细的了解另一种存储结构List<T>, List ...

  7. AI助力软件工程师高效工作:8款神器助你优化工作流程

    随着人工智能技术的不断发展,AI工具在软件工程领域展现出强大的应用潜力.善用 AI 工具可以消除繁琐事务带来的倦怠,帮助软件工程师更好地传达想法,完成更高质量的工作.我们可以将 AI 以各种方式应用于 ...

  8. 将Abp默认事件总线改造为分布式事件总线

    @ 目录 原理 创建分布式事件总线 实现自动订阅和事件转发 使用 启动Redis服务 配置 传递Abp默认事件 传递自定义事件 项目地址 原理 本地事件总线是通过Ioc容器来实现的. IEventBu ...

  9. 文心一言 VS 讯飞星火 VS chatgpt (170)-- 算法导论13.2 3题

    三.用go语言,设在图 13-2 左边一棵树中,a.b和c 分别为子树a.β和γ中的任意结点.当结点 x 左旋之后,a.b和c 的深度会如何变化? 文心一言: 在二叉树中,左旋操作是改变节点的子节点顺 ...

  10. 基于FPGA的电子琴设计(按键和蜂鸣器)---第一版---郝旭帅电子设计团队

    本篇为各位朋友介绍基于FPGA的电子琴设计(按键和蜂鸣器)----第一版. 功能说明: 外部输入七个按键,分别对应音符的"1.2.3.4.5.6.7",唱作do.re.mi.fa. ...