Qt 操作Json格式文件(创建插入解析修改删除)

Posted cpp_learner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt 操作Json格式文件(创建插入解析修改删除)相关的知识,希望对你有一定的参考价值。

花了几天时间研究Qt如何操作Json文件,也是有一点心得,现在记录下来分享!

为什么要学习Json呢?Json是一个轻量级数据存储文件,其里面使用了大量的字符进行存储数据。JSON 是存储和交换文本信息的语法,类似 XML。JSON 比 XML 更小、更快,更易解析。

JSON 是一种编码来自 javascript 的对象数据的格式,但现在已广泛用作互联网上的数据交换格式。
Qt 中的 JSON 支持提供了易于使用的C++ API 来解析、修改和保存 JSON 数据。

当然,我学习Json,主要是因为我的上一篇博客中学习了Qt的Socket编程,个人觉得,如果是需要在TCP与UDP进行数据传送的话,使用Json文件传输效率会比较高吧…个人理解,不喜勿喷!

所以呢,今天带来一篇,使用Qt操作Json格式文件的博客,供大家参考、借鉴!



一、准备工作

VS编译器创建项目时,勾选Core项
在这里插入图片描述
QT编译器需要在.pro文件中 QT += Core

操作Json文件所需要用到的类:

类说明
QJsonDocument读写JSON文档
QJsonObject封装JSON对象 { }
QJsonArray封装JSON数组 [ ]
QJsonValue封装JSON值 int,float,double,bool,{ },[ ]等
QJsonParseError报告JSON处理过程中出现的错误

操作Json文件所需要用到的头文件:
#include < QJsonObject > // { }
#include < QJsonArray > // [ ]
#include < QJsonDocument > // 解析Json
#include < QJsonValue > // int float double bool null { } [ ]
#include < QJsonParseError >

下图是这篇博客所操作的JSON文件:
在这里插入图片描述


二、封装Json

  1. { }

    "interest": {
    	"basketball": "篮球",
    	"badminton": "羽毛球"
    },
    

    代码实现上述效果:

    // 定义 { } 对象
    QJsonObject interestObj;
    // 插入元素,对应键值对
    interestObj.insert("basketball", "篮球");
    interestObj.insert("badminton", "羽毛球");
    
  2. [ ]

    "color": [ "black", "white"],
    

    代码实现上述效果:

    // 定义 [ ] 对象
    QJsonArray colorArray;
    // 往数组中添加元素
    colorArray.append("black");
    colorArray.append("white");
    
  3. [ { } { } ]

    "like": [
    	{ "game": "三国杀", "price": 58.5 },
    	{ "game": "海岛奇兵", "price": 66.65 }
    ],
    

    代码实现上述效果:

    // 定义 { } 对象
    QJsonObject likeObject1;
    likeObject1.insert("game", "三国杀");
    likeObject1.insert("price", 58.5);
    
    QJsonObject likeObject2;
    likeObject2.insert("game", "海岛奇兵");
    likeObject2.insert("price", 66.65);
    
    // 定义 [ ] 对象
    QJsonArray likeArray;
    likeArray.append(likeObject1);
    likeArray.append(likeObject2);
    
  4. { { } { } }

    "languages": {
    	"serialOne": { "language": "汉语", "grade": 10 },
    	"serialTwo": { "language": "英语", "grade": 6 }
    },
    

    代码实现上述效果:

    // 定义 { } 对象
    QJsonObject language1;
    language1.insert("language", "汉语");
    language1.insert("grade", 10);
    
    QJsonObject language2;
    language2.insert("language", "英语");
    language2.insert("grade", 6);
    
    QJsonObject languages;
    // 将{ } 插入 { } 中
    languages.insert("serialOne", language1);
    languages.insert("serialTwo", language2);
    
  5. 定义根节点 也即是最外层 { }

    // 定义根节点	也即是最外层 { }
    QJsonObject rootObject;
    
  6. 将上面定义的{ } 与 [ ] 都插入到跟节点{ }中

    // 插入元素
    rootObject.insert("name", "老王");
    rootObject.insert("age", 26);
    rootObject.insert("interest", interestObj);
    rootObject.insert("color", colorArray);
    rootObject.insert("like", likeArray);
    rootObject.insert("languages", languages);
    rootObject.insert("vip", true);
    rootObject.insert("address", QJsonValue::Null);
    
  7. 实例化QJsonDocument对象

    // 将json对象里的数据转换为字符串
    QJsonDocument doc;
    // 将object设置为本文档的主要对象
    doc.setObject(rootObject);
    
  8. Json字符串保存到json文件里

    QFile file("../Json/js.json");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
    	qDebug() << "can't open error!";
    	return;
    
    }
    
    QTextStream stream(&file);
    stream.setCodec("UTF-8");		// 设置写入编码是UTF8
    // 写入文件
    stream << doc.toJson();
    file.close();
    

    这里需要注意的是,我们写入文件时,指定的编码是UTF8,所以在读取出来时也需要使用UTF8编码进行读取!

把代码写好后,编译运行,会在自己的项目路径中创建一个JSON文件,并写入内容,文件内容如下:
在这里插入图片描述
顺序可能有点乱,但是不妨碍我们阅读与下面解析!


三、解析Json

解析根据上图进行!

在使用JSON对象或者JSON数组对象得到对应的value之后,该value值并不是最总的数据类型,而是一个QJsonValue类型的属性,我们必须通过该对象判断该类型的实际类型,然后在将其转换为对应的数据类型。
可以使用下面表格的方法,也可以使用代码中的方法进行判断,
类型判断相关成员方法:

方法解释
bool isArray() const是否为json数组
bool isBool() const是否为布尔类型
bool isDouble() const是否为浮点类型
bool isNull() const是否为空
bool isObject() const是否为json对象
bool isString() const是否为字符串类型
  1. 打开文件,读取全部内容

    QFile file("../Json/js.json");
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
    	qDebug() << "can't open error!";
    	return;
    }
    
    // 读取文件的全部内容
    QTextStream stream(&file);
    stream.setCodec("UTF-8");		// 设置读取编码是UTF8
    QString str = stream.readAll();
    
    file.close();
    

    注意编码啊!

  2. 将字符串解析成QJsonDocument对象

    // QJsonParseError类用于在JSON解析期间报告错误。
    QJsonParseError jsonError;
    // 将json解析为UTF-8编码的json文档,并从中创建一个QJsonDocument。
    // 如果解析成功,返回QJsonDocument对象,否则返回null
    QJsonDocument doc = QJsonDocument::fromJson(str.toUtf8(), &jsonError);
    // 判断是否解析失败
    if (jsonError.error != QJsonParseError::NoError && !doc.isNull()) {
    	qDebug() << "Json格式错误!" << jsonError.error;
    	return;
    }
    
  3. 获取根 { }

    QJsonObject rootObj = doc.object();
    
  4. 根据键获取值

    // 根据键获取值
    QJsonValue nameValue = rootObj.value("name");
    qDebug() << "name = " << nameValue.toString();
    
    
    QJsonValue ageValue = rootObj.value("age");
    qDebug() << "age = " << ageValue.toInt();
    // 解析 bool类型
    QJsonValue vipValue = rootObj.value("vip");
    qDebug() << "vip = " << vipValue.toBool();
    
    
    // 解析 null类型
    QJsonValue addressValue = rootObj.value("address");
    if (addressValue.type() == QJsonValue::Null) {
    	qDebug() << "address = " << "null";
    }
    
  5. 解析对象 { }
    也就是解析下图内容:
    在这里插入图片描述

    解析代码:

    QJsonValue interestValue = rootObj.value("interest");
    // 判断是否是object类型
    if (interestValue.type() == QJsonValue::Object) {
    	// 转换为QJsonObject类型
    	QJsonObject interestObj = interestValue.toObject();
    
    	QJsonValue basketballValue = interestObj.value("basketball");
    	qDebug() << "basketball = " << basketballValue.toString();
    	QJsonValue badmintonValue = interestObj.value("badminton");
    	qDebug() << "badminton = " << badmintonValue.toString();
    }
    

    通过value函数根据键获取到一个QJsonValue 类型数据,然后进行判断是否是对应类型,然后转换成对应类型,就可以使用value函数进行获取QJsonValue值,再转换类型就可以拿到数据了。

  6. 解析数组 [ ]
    也就是解析下图内容:
    在这里插入图片描述
    解析代码:

    QJsonValue colorValue = rootObj.value("color");
    // 判断是否是Array类型
    if (colorValue.type() == QJsonValue::Array) {
    	// 转换为QJsonArray类型
    	QJsonArray colorArray = colorValue.toArray();
    
    	for (int i = 0; i < colorArray.size(); i++) {
    		QJsonValue color = colorArray.at(i);
    		qDebug() << "color = " << color.toString();
    	}
    }
    
  7. 解析数组中的对象 [ { } ]
    也就是解析下图内容:
    在这里插入图片描述
    解析代码:

    // 根键获取值
    QJsonValue likeValue = rootObj.value("like");
    // 判断类型是否是数组类型
    if (likeValue.type() == QJsonValue::Array) {
    	// 转换成数组类型
    	QJsonArray likeArray = likeValue.toArray();
    	// 遍历数组
    	for (int i = 0; i < likeArray.count(); i++) {
    		// 获取数组的第一个元素,类型是QJsonValue 
    		QJsonValue likeValueChild = likeArray.at(i);
    		// 判断是不是对象类型
    		if (likeValueChild.type() == QJsonValue::Object) {
    			// 转换成对象类型
    			QJsonObject likeObj = likeValueChild.toObject();
    			// 最后通过value函数就可以获取到值了,解析成功!
    			QJsonValue gameLikeValue = likeObj.value("game");
    			qDebug() << "game = " << gameLikeValue.toString();
    			QJsonValue priceLikeValue = likeObj.value("price");
    			qDebug() << "price = " << priceLikeValue.toDouble();
    		}
    	}
    }
    
  8. 解析 对象 中 对象 { { } }
    也就是解析下图内容:
    在这里插入图片描述
    解析代码:

    // 根据建获取值
    QJsonValue languagesValue = rootObj.value("languages");
    // 判断是不是对象类型
    if (languagesValue.type() == QJsonValue::Object) {
    	// 转换成对象类型
    	QJsonObject languagesObj = languagesValue.toObject();
    	// 根据建获取值
    	QJsonValue serialOneValue = languagesObj.value("serialOne");
    	// 判断是不是对象类型
    	if (serialOneValue.type() == QJsonValue::Object) {
    		// 转换成对象类型
    		QJsonObject serialOneObj = serialOneValue.toObject();
    		// 根据建获取值
    		QJsonValue languageValue = serialOneObj.value("language");
    		// 最后转换成对应类型就解析出来了!
    		qDebug() << "language = " << languageValue.toString();
    		QJsonValue gradeValue = serialOneObj.value("grade");
    		qDebug() << "grade = " << gradeValue.toInt();
    	}
    
    	QJsonValue serialTwoValue = languagesObj.value("serialTwo");
    	if (serialTwoValue.type() == QJsonValue::Object) {
    		QJsonObject serialTwoObj = serialTwoValue.toObject();
    
    		QJsonValue languageValue = serialTwoObj.value("language");
    		qDebug() << "language = " << languageValue.toString();
    		QJsonValue gradeValue = serialTwoObj.value("grade");
    		qDebug() << "grade = " << gradeValue.toInt();
    	}
    }
    

解析运行结果如下:
在这里插入图片描述

四、修改Json

修改的过程就是:将数据从文件中读取出来,解析成QJsonDocument对象后,在获取跟对象{ },通过跟对象在获取其他的对象{}或者数组[],修改后,再赋值给跟对象{},达到替换效果,也就是修改了,最后再写入文件即可!

  1. 读取数据解析成QJsonDocument代码省略,跟上面一样

  2. 获取根节点对象

    // 获取根 { }
    QJsonObject rootObj = doc.object();
    
  3. 修改属性

    // 修改name属性
    rootObj["name"] = "老李";
    rootObj["vip"] = false;
    

    修改前:
    在这里插入图片描述
    修改后:
    在这里插入图片描述

  4. 修改数组 [ ] 中的元素

    QJsonValue colorValue = rootObj.value("color");
    if (colorValue.type() == QJsonValue::Array) {
    	QJsonArray colorArray = colorValue.toArray();
    
    	// 修改数组中的值
    	colorArray.replace(0, "blue");
    	colorArray.replace(1, "green");
    
    	// 赋值覆盖原有数组属性
    	rootObj["color"] = colorArray;
    }
    

    修改前:
    在这里插入图片描述
    修改后:
    在这里插入图片描述

  5. 修改 { } 中的值

    QJsonValue interestValue = rootObj.value("interest");
    if (interestValue.type() == QJsonValue::Object) {
    	QJsonObject interestObject = interestValue.toObject();
    
    	interestObject["badminton"] = "乒乓球";
    	interestObject["basketball"] = "足球";
    
    	rootObj["interest"] = interestObject;
    }
    

    修改前:
    在这里插入图片描述

    修改后:
    在这里插入图片描述

  6. 修改 { { } } 中的值

    QJsonValue languagesValue = rootObj.value("languages");
    if (languagesValue.type() == QJsonValue::Object) {
    	QJsonObject languagesObj = languagesValue.toObject();
    
    	// 找到内部第一个 { }
    	QJsonValue serialOneValue = languagesObj.value("serialOne");
    	if (serialOneValue.type() == QJsonValue::Object) {
    		QJsonObject serialOneObj = serialOneValue.toObject();
    
    		serialOneObj["grade"] = "20";
    
    		languagesObj["serialOne"] = serialOneObj;
    	}
    
    	// 找到内部第二个 { }
    	QJsonValue serialTwoValue = languagesObj.value("serialTwo");
    	if (serialTwoValue.type() == QJsonValue::Object) {
    		QJsonObject serialTwoObj = serialTwoValue.toObject();
    
    		serialTwoObj["grade"] = "10";
    		serialTwoObj["language"] = "粤语";
    
    		languagesObj["serialTwo"] = serialTwoObj;
    	}
    
    	rootObj["languages"] = languagesObj;
    }
    

    修改前:
    在这里插入图片描述
    修改后:
    在这里插入图片描述

  7. 修改 [ { } ]

    QJsonValue likeValue = rootObj.value("like");
    if (likeValue.type() == QJsonValue::Array) {
    	QJsonArray likeArray = likeValue.toArray();
    
    	// 根据索引获得对应{ }
    	QJsonObject obj1 = likeArray[0].toObject();
    	obj1["game"] = "欢乐斗地主";
    	obj1["price"] = 88.8;
    	QJsonObject obj2 = likeArray[1].toObject();
    	obj2["game"] = "欢乐斗牛";
    	obj2["price"] = 77.7;
    
    	// 替换覆盖
    	likeArray.repl

    以上是关于Qt 操作Json格式文件(创建插入解析修改删除)的主要内容,如果未能解决你的问题,请参考以下文章

    C/C++ 使用cjson库 操作Json格式文件(创建插入解析修改删除)

    C/C++ 使用 tinyxml库 操作XML格式文件(创建插入删除修改解析)

    C/C++ 使用 tinyxml库 操作XML格式文件(创建插入删除修改解析)

    QT Excel 插入、删除或者更改数据之后保存保存失败

    QT学习_QT解析Json格式文件

    Hive基础知识