C/C++ 使用rapidjson库 操作Json格式文件(创建、插入、解析、修改、删除)
目录
一、前言
1.简介
2.兼容性
3.下载
4.安装
5.官方文档
6.自述
二、封装Json
1. 创建一个 Document 对象
2. "key":"value"
3. { }
4. [ ]
5. [ { }, { } ]
6. [ [ ], [ ] ]
7. { [ ], [ ] }
8. { { }, { } }
9. 将Document转换为字符串输出
10. 写入文件中
三、解析Json
1. 打开文件读取josn数据
2. 使用读取到的json数据初始化Document对象
3. 直接通过键进行解析
4. 解析对象 { }
5. 解析数组 [ ]
6. 解析数组中的对象 [ { } ]
7. 解析数组中的数组 [ [ ] [ ] ]
8. 解析对象中的数组 { [ ], [ ] }
9. 解析对象中的对象 { { } }
10. 解析结果
四、修改Json
1. 读取json数据并初始化Document对象
2. 直接修改值
3. 修改 { } 中的值
4. 修改数组 [ ] 中的值
5. 修改 [ { } ] 中的值
6. 修改 [ [ ] ] 中的值
7. 修改 { [ ] } 中的值
8. 修改 { { } } 中的值
9. 将Document转换为字符串并写入文件
五、删除Json
1. 读取json数据并初始化Document对象
2. 直接删除
3. 删除 { } 中的值
4. 删除数组 [ ] 中的元素
5. 删除 [ ] 中的 { }
6. 删除 [ ] 中的 [ ]
7. 删除 { } 中的 [ ]
8. 删除 { } 中的 { }
9. 将Document转换为字符串并写入文件
六、全部代码汇总
.h文件
.cpp文件
七、总结
一、前言
1.简介
RapidJSON 是一个 C++ 的 JSON 解析器及生成器。它的灵感来自 RapidXml。
- RapidJSON 小而全。它同时支持 SAX 和 DOM 风格的 API。SAX 解析器只有约 500 行代码。
- RapidJSON 快。它的性能可与
strlen()
相比。可支持 SSE2/SSE4.2 加速。 - RapidJSON 独立。它不依赖于 BOOST 等外部库。它甚至不依赖于 STL。
- RapidJSON 对内存友好。在大部分 32/64 位机器上,每个 JSON 值只占 16 字节(除字符串外)。它预设使用一个快速的内存分配器,令分析器可以紧凑地分配内存。
- RapidJSON 对 Unicode 友好。它支持 UTF-8、UTF-16、UTF-32 (大端序/小端序),并内部支持这些编码的检测、校验及转码。例如,RapidJSON 可以在分析一个 UTF-8 文件至 DOM 时,把当中的 JSON 字符串转码至 UTF-16。它也支持代理对(surrogate pair)及
"\u0000"
(空字符)。
JSON(JavaScript Object Notation)是一个轻量的数据交换格式。RapidJSON 应该完全遵从 RFC7159/ECMA-404,并支持可选的放宽语法。
2.兼容性
RapidJSON 是跨平台的。
3.下载
https://github.com/Tencent/rapidjson/
4.安装
RapidJSON 是只有头文件的 C++ 库。只需把 include/rapidjson
目录复制至系统或项目的 include 目录中。
5.官方文档
RapidJSON: 首页
以上所提到的,均来自rapidjson官方文档!
6.自述
之前我已经学过了QT如何操作json,然后又学过了使用cjson库,那为什么我还会继续学习rapidjson库呢?
原因很简单,QT自带的json库有bug,当json数据大于100mb的时候,QT是处理不了的;之前做项目被QT这个bug坑惨了。
然后cjson也是轻量级别的,所以也是使用不了。
最后不得已,在网上调研,终于找到一个json库是开源的,可以直接将源码添加到的项目中的,而且还是跨平台,最重要的是,它可以处理超过100mb的json数据,这完全符合我的需求,最后简单学习了一下该库后,并在项目中用上了,效果还行,值得推荐。他就是rapidjson,由腾讯开源的一个json库。特别适合需要处理大型JSON数据的C++开发者使用,解决了QT自带JSON库处理大文件的限制问题。
下图是这篇博客所操作的JSON文件:
使用时记得添加头文件:
#include "include/rapidjson/document.h"
#include "include/rapidjson/writer.h"
#include "include/rapidjson/prettywriter.h"
#include "include/rapidjson/stringbuffer.h"
注意:每个 JSON 值都储存为 Value
类,而 Document
类则表示整个 DOM,它存储了一个 DOM 树的根 Value
。RapidJSON 的所有公开类型及函数都在 rapidjson
命名空间中。
重要的枚举:
enum Type { kNullType = 0, //!< null kFalseType = 1, //!< false kTrueType = 2, //!< true kObjectType = 3, //!< object kArrayType = 4, //!< array kStringType = 5, //!< string kNumberType = 6 //!< number
};
一般来说,调用rapidjson库的函数,都需要在最后一个参数中给其指定分配内存,一般使用Document::GetAllocator()函数进行传参即可。
二、封装Json
1. 创建一个 Document 对象
// 创建一个 Document 对象
rapidjson::Document doc;
// 将Document对象设置为一个Object类型
doc.SetObject();
2. "key":"value"
实现效果:
代码实现上述效果:
std::string keyName = "name";
QString keyValue = "小明";
bool vip = false; // 如果字符串非常量,需要转换为c语言字符串; name = "小明"
doc.AddMember(rapidjson::Value(keyName.c_str(), doc.GetAllocator()), rapidjson::Value(keyValue.toUtf8().constData(), doc.GetAllocator()), doc.GetAllocator());
// 如果字符串是常量,可直接传参; age = 25
doc.AddMember("age", 25, doc.GetAllocator());
// vip = false
doc.AddMember("vip", vip, doc.GetAllocator());
// address = null
doc.AddMember("address", rapidjson::Value(rapidjson::kNullType), doc.GetAllocator());
最后一个参数是内存的分配器,通常使用doc.GetAllocator()获取;
3. { }
实现效果:
代码实现上述效果:
// 1.定义一个空的对象 { }
rapidjson::Value interest(rapidjson::kObjectType);
// 2.往对象中插入数据
interest.AddMember("basketball", rapidjson::Value("篮球", doc.GetAllocator()), doc.GetAllocator());
interest.AddMember("badminton", rapidjson::Value("羽毛球", doc.GetAllocator()), doc.GetAllocator());
// 3.添加到doc中
doc.AddMember("interest", interest, doc.GetAllocator());
如果键或者值是常量,都可以直接使用常量字符串;
interest.AddMember("basketball", "篮球", doc.GetAllocator());
4. [ ]
实现效果:
代码实现上述效果:
// 定义一个空的数组 [ ]
rapidjson::Value color(rapidjson::kArrayType);
color.PushBack("yellow", doc.GetAllocator());
color.PushBack("gray", doc.GetAllocator());
// 添加到doc中
doc.AddMember("color", color, doc.GetAllocator());
如果需要移除最后一个可以使用:color.PopBack();
5. [ { }, { } ]
实现效果:
代码实现上述效果:
// 数组包含对象 [ {}, {} ]
QList<QString> gameList = { "马里奥", "魂斗罗", "雪人兄弟" };
QList<double> pricesList = { 55.55, 66.66, 77 };
// 1.定义空数组
rapidjson::Value like(rapidjson::kArrayType);
for (int i = 0; i < gameList.count(); ++i) { // 2.定义空的对象 rapidjson::Value gameObj(rapidjson::kObjectType); // 3.往对象中插入数据 gameObj.AddMember("game", rapidjson::Value(gameList[i].toUtf8().constData(), doc.GetAllocator()),doc.GetAllocator()); gameObj.AddMember("price", pricesList[i], doc.GetAllocator()); // 4.添加到数组中 like.PushBack(gameObj, doc.GetAllocator());
}
// 5.数组添加到doc中
doc.AddMember("like", like, doc.GetAllocator());
6. [ [ ], [ ] ]
实现效果:
代码实现上述效果:
// 数组包含数组 [ [], [] ]
QList<QList<QString>> schoolList = { { "小学", "初中" }, { "高中", "大学" } };
// 1.定义空数组
rapidjson::Value education(rapidjson::kArrayType);
for (int i = 0; i < schoolList.count(); ++i) { // 2.定义空数组 rapidjson::Value tmpArray(rapidjson::kArrayType); QList<QString> tmpList = schoolList[i]; for (int j = 0; j < tmpList.count(); ++j) { // 3.往数组中插入数据 tmpArray.PushBack(rapidjson::Value(tmpList.at(j).toUtf8().constData(), doc.GetAllocator()), doc.GetAllocator()); } // 4.数组插入到数组中 education.PushBack(tmpArray, doc.GetAllocator());
}
// 5.数组包含数组 插入到doc中
doc.AddMember("education", education, doc.GetAllocator());
7. { [ ], [ ] }
实现效果:
代码实现上述效果:
// 对象包含数组 { [], [] }
QList<QList<int>> intList = { { 1, 2 }, { 3, 4 } };
// 1.定义空的对象
rapidjson::Value number(rapidjson::kObjectType);
for (int i = 0; i < intList.count(); ++i) { QList<int> tmpList = intList[i]; // 2.定义空的数组 rapidjson::Value tmpArr(rapidjson::kArrayType); for (int j = 0; j < tmpList.count(); ++j) { // 3.往数组中插入数据 tmpArr.PushBack(tmpList.at(j), doc.GetAllocator()); } // 4.数组插入到对象中 QString key = QString("num%1").arg(i+1); // 插入到对象中,需要指定key,且不能重名 number.AddMember(rapidjson::Value(key.toUtf8().constData(), doc.GetAllocator()),tmpArr, doc.GetAllocator());
}
// 5.对象包含数组 插入到doc中
doc.AddMember("number", number, doc.GetAllocator());
8. { { }, { } }
实现效果:
代码实现上述效果:
// 对象包含对象 { {}, {} }
// 1.定义空的对象
rapidjson::Value languages(rapidjson::kObjectType); // 2.定义空的子对象,并插入数据
rapidjson::Value serialOne(rapidjson::kObjectType);
serialOne.AddMember("language", "汉语", doc.GetAllocator());
serialOne.AddMember("grade", 10, doc.GetAllocator());
rapidjson::Value serialTwo(rapidjson::kObjectType);
serialTwo.AddMember("language", "英语", doc.GetAllocator());
serialTwo.AddMember("grade", 4, doc.GetAllocator()); // 3.对象插入到对象中
languages.AddMember("serialOne", serialOne, doc.GetAllocator());
languages.AddMember("serialTwo", serialTwo, doc.GetAllocator());// 4.对象包含对象 插入到doc中
doc.AddMember("languages", languages, doc.GetAllocator());
9. 将Document转换为字符串输出
// 将Document转换为字符串输出
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 默认带换行和缩进
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray); // 格式会紧凑一点点
doc.Accept(writer); QByteArray jsonArr = buffer.GetString();
qDebug() << QString(jsonArr);
10. 写入文件中
#define JSON_FILE "test.json"// 写入文件
writeStrToFile1(JSON_FILE, jsonArr);bool Widget::writeStrToFile1(const QString &fileName, const QByteArray &data)
{QFile file(fileName);if (file.open(QIODevice::WriteOnly)) {file.write(data);} else {return false;}file.close();return true;
}
将json字符串写入文件后,得到如下:
三、解析Json
1. 打开文件读取josn数据
// 读取文件中的json数据
QString jsonStr = readFileAllStr(JSON_FILE);
qDebug() << jsonStr; QString Widget::readFileAllStr(const QString &fileName)
{QString str = nullptr;QFile file2(fileName);if (file2.open(QIODevice::ReadOnly | QIODevice::Text)) {QTextStream in(&file2);in.setCodec("UTF-8");str = in.readAll();file2.close();}return str;
}
2. 使用读取到的json数据初始化Document对象
// 创建一个 Document 对象
rapidjson::Document doc; // 解析 JSON 字符串
if (doc.Parse(jsonStr.toUtf8().constData()).HasParseError()) {qWarning() << "JSON 解析错误!"; return ;
}
3. 直接通过键进行解析
// 访问 JSON 数据// name
if (doc.HasMember("name") && doc["name"].IsString()) {QString name = doc["name"].GetString();rapidjson::Value name1(doc["name"], doc.GetAllocator());qDebug() << "name = " << name; // 输出有带 " "qDebug() << "name1 = " << name1.GetString(); // 输出没有带 " "
}// age
if (doc.HasMember("age") && doc["age"].IsInt()) {int age = doc["age"].GetInt();rapidjson::Value age1(doc["age"], doc.GetAllocator());// 他俩没有区别qDebug() << "age = " << age;qDebug() << "age1 = " << age1.GetInt();
}// vip
if (doc.HasMember("vip") && doc["vip"].IsBool()) {bool vip = doc["vip"].GetBool();rapidjson::Value vip1(doc["vip"], doc.GetAllocator());// 他俩没有区别qDebug() << "vip = " << vip;qDebug() << "vip1 = " << vip1.GetBool();
}// address
if (doc.HasMember("address") && doc["address"].IsNull()) {qDebug() << "address = null";
}
输出如下:
4. 解析对象 { }
也就是解析下图内容:
解析代码:
// 解析 { }
if (doc.HasMember("interest") && doc["interest"].IsObject()) {// 1.获得对象
// const rapidjson::Value &interest = doc["interest"].GetObj();rapidjson::Value interest(doc["interest"], doc.GetAllocator());if (interest.IsObject()) {// 2.获得对象内的值if (interest.HasMember("basketball") && interest["basketball"].IsString()) {QString basketball = interest["basketball"].GetString();qDebug() << "basketball = " << basketball;}// 3.另一种方式rapidjson::Value::ConstMemberIterator itr = interest.FindMember("badminton");if (interest.MemberEnd() != itr && interest["badminton"].IsString()) {QString badminton = interest["badminton"].GetString();qDebug() << "badminton = " << badminton;}}
}
也可以通过迭代器方式解析:
rapidjson::Value::ConstMemberIterator itr = doc.FindMember("interest");
if (doc.MemberEnd() != itr) {// 1.获得对象
// const rapidjson::Value &interest = doc["interest"].GetObj();rapidjson::Value interest(doc["interest"], doc.GetAllocator());if (interest.IsObject()) {// 2.获得对象内的值rapidjson::Value::ConstMemberIterator it = interest.MemberBegin();for (; it != interest.MemberEnd(); ++it) {QString key = it->name.GetString();QString value = it->value.GetString();qDebug() << key << " = " << value;}}
}
5. 解析数组 [ ]
也就是解析下图内容:
解析代码:
// 解析 [ ]
// if (doc.HasMember("color") && doc["color"].IsArray()) {
rapidjson::Value::ConstMemberIterator itr = doc.FindMember("color");
if (doc.MemberEnd() != itr && doc["color"].IsArray()) {// 1.获得对象
// const rapidjson::Value &color = doc["color"].GetArray();rapidjson::Value color(doc["color"], doc.GetAllocator());if (color.IsArray()) {// 2.数组可通过直接for遍历获取值for (rapidjson::SizeType i = 0; i < color.Size(); ++i) {QString value = color[i].GetString();qDebug() << "value = " << value;}}
}
6. 解析数组中的对象 [ { } ]
也就是解析下图内容:
解析代码:
// 解析 [ {} ]
// 1.查找doc是否有 like
rapidjson::Value::ConstMemberIterator itlike = doc.FindMember("like");
if (doc.MemberEnd() != itlike && doc["like"].IsArray()) {// 2.获得like数组const rapidjson::Value &like = doc["like"].GetArray();if (like.IsArray()) {// 3.遍历like数组for (rapidjson::SizeType i = 0; i < like.Size(); ++i) {// 4.获得数组内的对象const rapidjson::Value &obj = like[i].GetObj();if (obj.IsObject()) {// 5.获得对象内的值rapidjson::Value::ConstMemberIterator it = obj.MemberBegin();for (; it != obj.MemberEnd(); ++it) {QString key = it->name.GetString();// 6.注意获取值的类型,否则程序会闪退;(所以,一般推荐json的值都使用字符串存储)QString value = it->value.IsString() ? it->value.GetString() : QString::number(it->value.GetDouble());qDebug() << key << " = " << value;}}}}
}
7. 解析数组中的数组 [ [ ] [ ] ]
也就是解析下图内容:
解析代码:
// 解析 [ [] ]
// 1.查找doc是否有 education
rapidjson::Value::ConstMemberIterator iteducation = doc.FindMember("education");
if (doc.MemberEnd() != iteducation && doc["education"].IsArray()) {// 2.获得education数组const rapidjson::Value &education = doc["education"].GetArray();if (education.IsArray()) {// 3.遍历education数组for (rapidjson::SizeType i = 0; i < education.Size(); ++i) {// 4.获得数组内的数组const rapidjson::Value &arr = education[i].GetArray();// 5.遍历数组,获得数组内的元素for (rapidjson::SizeType j = 0; j < arr.Size(); ++j) {QString value = arr[j].GetString();qDebug() << "value = " << value;}}}
}
8. 解析对象中的数组 { [ ], [ ] }
也就是解析下图内容:
解析代码:
// 解析 { [] }
// 1.查找doc是否有 education
rapidjson::Value::ConstMemberIterator itnumber = doc.FindMember("number");
if (doc.MemberEnd() != itnumber && doc["number"].IsObject()) {// 2.获得number对象const rapidjson::Value &number = doc["number"].GetObj();if (number.IsObject()) {// 3.获得对象内的数组rapidjson::Value::ConstMemberIterator itnum1 = number.FindMember("num1");if (number.MemberEnd() != itnum1 && number["num1"].IsArray()) {const rapidjson::Value &num1 = number["num1"].GetArray();if (num1.IsArray()) {// 4.遍历数组获得里面的值for (rapidjson::SizeType i = 0; i < num1.Size(); ++i) {int value = num1[i].GetInt();qDebug() << "value = " << value;}}}rapidjson::Value::ConstMemberIterator itnum2 = number.FindMember("num2");if (number.MemberEnd() != itnum2 && number["num2"].IsArray()) {const rapidjson::Value &num2 = number["num2"].GetArray();for (rapidjson::SizeType i = 0; i < num2.Size(); ++i) {int value = num2[i].GetInt();qDebug() << "value = " << value;}}}
}
9. 解析对象中的对象 { { } }
也就是解析下图内容:
解析代码:
// 解析 { {} }
// 1.查找languages对象
rapidjson::Value::ConstMemberIterator itLanguages = doc.FindMember("languages");
if (doc.MemberEnd() != itLanguages && doc["languages"].IsObject()) {// 2.获得languages对象const rapidjson::Value &languages = doc["languages"].GetObj();// 3.查找serialOne对象rapidjson::Value::ConstMemberIterator itSerialOne = languages.FindMember("serialOne");if (languages.MemberEnd() != itSerialOne && languages["serialOne"].IsObject()) {// 4.获得serialOne对象const rapidjson::Value &serialOne = languages["serialOne"].GetObj();// 5.获得serialOne对象内的值if (serialOne.HasMember("language") && serialOne["language"].IsString()) {QString basketball = serialOne["language"].GetString();qDebug() << "language = " << basketball;}if (serialOne.HasMember("grade") && serialOne["grade"].IsInt()) {int grade = serialOne["grade"].GetInt();qDebug() << "grade = " << grade;}}// 3.查找serialTwo对象rapidjson::Value::ConstMemberIterator itSerialTwo = languages.FindMember("serialTwo");if (languages.MemberEnd() != itSerialTwo && languages["serialTwo"].IsObject()) {// 4.获得serialTwo对象const rapidjson::Value &serialTwo = languages["serialOne"].GetObj();// 5.获得对象内的值rapidjson::Value::ConstMemberIterator it = serialTwo.MemberBegin();for (; it != serialTwo.MemberEnd(); ++it) {QString key = it->name.GetString();// 注意获取值的类型,否则程序会闪退;(所以,一般推荐json的值都使用字符串存储)QString value = it->value.IsString() ? it->value.GetString() : QString::number(it->value.GetInt());qDebug() << key << " = " << value;}}
}
10. 解析结果
四、修改Json
1. 读取json数据并初始化Document对象
// 读取文件中的json数据
QString jsonStr = readFileAllStr(JSON_FILE);
qDebug() << jsonStr;// 创建一个 Document 对象
rapidjson::Document doc;// 解析 JSON 字符串
if (doc.Parse(jsonStr.toStdString().c_str()).HasParseError()) {qWarning() << "JSON 解析错误!";return ;
}
2. 直接修改值
// 1.判断是否存在(注意,如果不存在,直接修改会报错,所以需要判断是否存在)
if (doc.HasMember("name")) {// 2.直接赋值修改即可doc["name"] = "小杨";
}if (doc.HasMember("age")) {doc["age"] = 100;
}if (doc.HasMember("vip")) {doc["vip"] = true;
}if (doc.HasMember("address")) {doc["address"] = "广东省...";
}
修改前:
修改后:
3. 修改 { } 中的值
// 修改 { }
if (doc.HasMember("interest") && doc["interest"].IsObject()) {// 1.获得对象rapidjson::Value interest(doc["interest"], doc.GetAllocator());// 2.修改对象内的值if (interest.HasMember("basketball")) {interest["basketball"] = "姚明";}// 另一种方式rapidjson::Value::ConstMemberIterator itr = interest.FindMember("badminton");if (interest.MemberEnd() != itr) {interest["badminton"] = "林丹";}// 3.修改完后重新赋值doc["interest"] = interest;
}
修改前:
修改后:
4. 修改数组 [ ] 中的值
// 修改 [ ] 内的值
// 1.查找是否存在数组
rapidjson::Value::ConstMemberIterator itColor = doc.FindMember("color");
if (doc.MemberEnd() != itColor) {// 2.获得数组rapidjson::Value color(doc["color"], doc.GetAllocator());// 3.准备修改的数据QStringList colorList = { "red", "blue" };// 4.数组可通过直接for遍历修改,也可以单独一个也给去修改,通过下标for (rapidjson::SizeType i = 0; i < color.Size(); ++i) {color[i].SetString(colorList[i].toUtf8().constData(), doc.GetAllocator());
// color[i].Set(colorList[i].toUtf8().constData()); // 也可以使用这个}// 5.修改完后重新赋值doc["color"] = color;
}
修改前:
修改后:
5. 修改 [ { } ] 中的值
// 修改 [ {} ] 内的值
// 1.查找是否存在数组
rapidjson::Value::ConstMemberIterator itLike = doc.FindMember("like");
if (doc.MemberEnd() != itLike) {// 2.获得数组rapidjson::Value like(doc["like"], doc.GetAllocator());// 3.准备修改的数据QStringList gameList = { "中国象棋", "围棋", "五子棋" };QList<double> priceList = { 77.7, 88.8 , 99.9 };// 4.数组可通过直接for遍历修改,也可以单独一个也给去修改,通过下标for (rapidjson::SizeType i = 0; i < like.Size(); ++i) {// 5.获得数组内的对象rapidjson::Value obj(like[i], doc.GetAllocator());// 修改字符串相关if (obj.HasMember("game")) {obj["game"].SetString(gameList[i].toUtf8().constData(), doc.GetAllocator());
// obj["game"].Set(gameList[i].toUtf8().constData(), doc.GetAllocator());}// 修改整形相关rapidjson::Value::ConstMemberIterator itr = obj.FindMember("price");if (obj.MemberEnd() != itr) {obj["price"] = priceList[i];}like[i] = obj;}// 5.修改完后重新赋值doc["like"] = like;
}
修改前:
修改后:
6. 修改 [ [ ] ] 中的值
// 修改 [ [] ] 内的值
// 1.查找是否存在数组
rapidjson::Value::ConstMemberIterator itEducation = doc.FindMember("education");
if (doc.MemberEnd() != itEducation) {// 2.获得数组rapidjson::Value education(doc["education"], doc.GetAllocator());// 可以使用数组方式去修改
// education[0][0] = "小学六年级";
// education[0][1] = "初中初三";
// education[1][0] = "高中高三";
// education[1][1] = "大学大四";// 3.准备修改的数据QList<QList<QString>> list = { { "小学六年级", "初中初三" }, { "高中高三", "大学大四" } };// 4.数组可通过直接for遍历修改,也可以单独一个也给去修改,通过下标for (rapidjson::SizeType i = 0; i < education.Size(); ++i) {// 5.获得数组内的数组rapidjson::Value arr(education[i], doc.GetAllocator());for (rapidjson::SizeType j = 0; j < arr.Size(); ++j) {// 修改值arr[j].SetString(list[i][j].toUtf8().constData(), doc.GetAllocator());
// arr[j].Set(list[i][j].toUtf8().constData(), doc.GetAllocator());}// 重新赋值education[i] = arr;}// 6.修改完后重新赋值doc["education"] = education;
}
修改前:
修改后:
7. 修改 { [ ] } 中的值
// 修改 { [] } 内的值
// 1.查找是否存在对象
rapidjson::Value::ConstMemberIterator itNumber = doc.FindMember("number");
if (doc.MemberEnd() != itNumber) {rapidjson::Value number(doc["number"], doc.GetAllocator());// 2.获得对象内的数组rapidjson::Value num1(number["num1"], doc.GetAllocator());for (rapidjson::SizeType i = 0; i < num1.Size(); ++i) {num1[i] = num1[i].GetInt() + 10;}rapidjson::Value num2(number["num2"], doc.GetAllocator());for (rapidjson::SizeType i = 0; i < num2.Size(); ++i) {num2[i] = num2[i].GetInt() + 10;}// 3.重新在赋值回来number["num1"] = num1;number["num2"] = num2;doc["number"] = number;
}
修改前:
修改后:
8. 修改 { { } } 中的值
// 修改 { { } } 内的值
// 1.查找是否存在对象
rapidjson::Value::ConstMemberIterator itLanguages = doc.FindMember("languages");
if (doc.MemberEnd() != itLanguages) {rapidjson::Value languages(doc["languages"], doc.GetAllocator());// 2.获得对象内的对象rapidjson::Value serialOne(languages["serialOne"], doc.GetAllocator());serialOne["language"].SetString("粤语", doc.GetAllocator());serialOne["grade"].SetInt(9);rapidjson::Value serialTwo(languages["serialTwo"], doc.GetAllocator());serialTwo["language"].SetString("白话", doc.GetAllocator());serialTwo["grade"].SetInt(8);// 3.重新在赋值回来languages["serialOne"] = serialOne;languages["serialTwo"] = serialTwo;doc["languages"] = languages;
}
修改前:
修改后:
9. 将Document转换为字符串并写入文件
// 将Document转换为字符串输出
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 默认带换行和缩进
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray); // 格式会紧凑一点点
doc.Accept(writer);QByteArray jsonArr = buffer.GetString();
qDebug() << QString(jsonArr);// 写入文件
writeStrToFile1(JSON_FILE, jsonArr);
五、删除Json
1. 读取json数据并初始化Document对象
// 读取文件中的json数据
QString jsonStr = readFileAllStr(JSON_FILE);
qDebug() << jsonStr;// 创建一个 Document 对象
rapidjson::Document doc;// 解析 JSON 字符串
if (doc.Parse(jsonStr.toStdString().c_str()).HasParseError()) {qWarning() << "JSON 解析错误!";return ;
}
2. 直接删除
// 1.直接删除即可
doc.RemoveMember("name");
doc.RemoveMember("age");
doc.RemoveMember("vip");
doc.RemoveMember("address");
3. 删除 { } 中的值
// 删除 { } 中的值
// 1.查找是否有对象
if (doc.HasMember("interest") && doc["interest"].IsObject()) {// 2.获得对象rapidjson::Value interest(doc["interest"], doc.GetAllocator());// 3.删除对象内的值interest.RemoveMember("badminton");// 4.删除完后重新赋值doc["interest"] = interest;
}
删除前:
删除后:
4. 删除数组 [ ] 中的元素
// 删除 [ ] 内的值
// 1.查找是否存在数组
rapidjson::Value::ConstMemberIterator itColor = doc.FindMember("color");
if (doc.MemberEnd() != itColor) {// 2.获得数组rapidjson::Value color(doc["color"], doc.GetAllocator());// 3.根据下表删除color.Erase(color.Begin() + 1); // 删除索引1的元素(第二个元素)//doc.RemoveMember("color"); // 删除键为"color"的整个数组//color.Clear(); // 清空数组,结果为"color":[]// 4.修改完后重新赋值doc["color"] = color;
}
删除前:
删除后:
5. 删除 [ ] 中的 { }
// 删除 [ {} ] 内的值
// 1.查找是否存在数组
rapidjson::Value::ConstMemberIterator itLike = doc.FindMember("like");
if (doc.MemberEnd() != itLike) {// 2.获得数组rapidjson::Value like(doc["like"], doc.GetAllocator());// 3.根据下表删除like.Erase(like.Begin() + 1); // 删除索引1的元素(第二个元素)// 4.修改完后重新赋值doc["like"] = like;
}
删除前:
删除后:
6. 删除 [ ] 中的 [ ]
// 删除 [ [] ] 内的值
// 1.查找是否存在数组
rapidjson::Value::ConstMemberIterator itEducation = doc.FindMember("education");
if (doc.MemberEnd() != itEducation) {// 2.获得数组rapidjson::Value education(doc["education"], doc.GetAllocator());// 3.根据下表删除education.Erase(education.Begin() + 1); // 删除索引1的元素(第二个元素)// 4.修改完后重新赋值doc["education"] = education;
}
删除前:
删除后:
7. 删除 { } 中的 [ ]
// 删除 { [] } 内的值
// 1.查找是否存在对象
rapidjson::Value::ConstMemberIterator itNumber = doc.FindMember("number");
if (doc.MemberEnd() != itNumber) {rapidjson::Value number(doc["number"], doc.GetAllocator());// 删除对象内的值number.RemoveMember("num2");doc["number"] = number;
}
删除前:
删除后:
8. 删除 { } 中的 { }
// 删除 { { } } 内的值
// 1.查找是否存在对象
rapidjson::Value::ConstMemberIterator itLanguages = doc.FindMember("languages");
if (doc.MemberEnd() != itLanguages) {rapidjson::Value languages(doc["languages"], doc.GetAllocator());// 删除对象内的值languages.RemoveMember("serialOne");doc["languages"] = languages;
}
删除前:
删除后:
9. 将Document转换为字符串并写入文件
// 将Document转换为字符串输出
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 默认带换行和缩进
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray); // 格式会紧凑一点点
doc.Accept(writer);QByteArray jsonArr = buffer.GetString();
qDebug() << QString(jsonArr);// 写入文件
writeStrToFile1(JSON_FILE, jsonArr);
六、全部代码汇总
rapidjson是纯源码的,所以,只需把 include/rapidjson
目录复制到自己的项目路径中即可(注意包含头文件)。
.h文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();/// 创建jsonvoid createJson();/// 解析jsonvoid parseJson();/// 修改jsonvoid modifyJson();/// 删除jsonvoid deleteJson();private:/*** @brief writeStrToFile 往空的文件中写入内容* @param fileNmae 文件路径* @param data 数据* @return*/bool writeStrToFile(const QString &fileNmae, const QByteArray &data);bool writeStrToFile1(const QString &fileName, const QByteArray &data);/*** @brief readFileAllByte 读取文件内的所有内容* @param fileName 文件路径* @return*/QByteArray readFileAllByte(const QString &fileName);QString readFileAllStr(const QString &fileName);private:Ui::Widget *ui;
};
#endif // WIDGET_H
.cpp文件
#include "widget.h"
#include "ui_widget.h"#include "include/rapidjson/document.h"
#include "include/rapidjson/writer.h"
#include "include/rapidjson/prettywriter.h"
#include "include/rapidjson/stringbuffer.h"#include <QDebug>
#include <QFile>#define JSON_FILE "test.json"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);createJson();parseJson();modifyJson();deleteJson();
}Widget::~Widget()
{delete ui;
}void Widget::createJson()
{// 创建一个 Document 对象rapidjson::Document doc;// 将Document对象设置为一个Object类型doc.SetObject();std::string keyName = "name";QString keyValue = "小明";bool vip = false;// 最后一个参数是内存的分配器,通常使用doc.GetAllocator()获取// 如果字符串非常量,需要转换为c语言字符串; name = "小明"doc.AddMember(rapidjson::Value(keyName.c_str(), doc.GetAllocator()),rapidjson::Value(keyValue.toUtf8().constData(), doc.GetAllocator()),doc.GetAllocator());// 如果字符串是常量,可直接传参; age = 25doc.AddMember("age", 25, doc.GetAllocator());// vip = falsedoc.AddMember("vip", vip, doc.GetAllocator());// address = nulldoc.AddMember("address", rapidjson::Value(rapidjson::kNullType), doc.GetAllocator());/*//! Type of JSON valueenum Type {kNullType = 0, //!< nullkFalseType = 1, //!< falsekTrueType = 2, //!< truekObjectType = 3, //!< objectkArrayType = 4, //!< arraykStringType = 5, //!< stringkNumberType = 6 //!< number};*/// 定义一个空的对象 { }rapidjson::Value interest(rapidjson::kObjectType);interest.AddMember("basketball", "篮球", doc.GetAllocator());interest.AddMember("badminton", rapidjson::Value("羽毛球", doc.GetAllocator()), doc.GetAllocator());// 添加到doc中doc.AddMember("interest", interest, doc.GetAllocator());// 定义一个空的数组 [ ]rapidjson::Value color(rapidjson::kArrayType);color.PushBack("yellow", doc.GetAllocator());color.PushBack("gray", doc.GetAllocator());// 添加到doc中doc.AddMember("color", color, doc.GetAllocator());// 数组包含对象 [ {}, {} ]QList<QString> gameList = { "马里奥", "魂斗罗", "雪人兄弟" };QList<double> pricesList = { 55.55, 66.66, 77 };// 1.定义空数组rapidjson::Value like(rapidjson::kArrayType);for (int i = 0; i < gameList.count(); ++i) {// 2.定义空的对象rapidjson::Value gameObj(rapidjson::kObjectType);// 3.往对象中插入数据gameObj.AddMember("game",rapidjson::Value(gameList[i].toUtf8().constData(), doc.GetAllocator()),doc.GetAllocator());gameObj.AddMember("price", pricesList[i], doc.GetAllocator());// 4.添加到数组中like.PushBack(gameObj, doc.GetAllocator());}// 5.数组添加到doc中doc.AddMember("like", like, doc.GetAllocator());// 数组包含数组 [ [], [] ]QList<QList<QString>> schoolList = { { "小学", "初中" }, { "高中", "大学" } };// 1.定义空数组rapidjson::Value education(rapidjson::kArrayType);for (int i = 0; i < schoolList.count(); ++i) {// 2.定义空数组rapidjson::Value tmpArray(rapidjson::kArrayType);QList<QString> tmpList = schoolList[i];for (int j = 0; j < tmpList.count(); ++j) {// 3.往数组中插入数据tmpArray.PushBack(rapidjson::Value(tmpList.at(j).toUtf8().constData(), doc.GetAllocator()), doc.GetAllocator());}// 4.数组插入到数组中education.PushBack(tmpArray, doc.GetAllocator());}// 5.数组包含数组 插入到doc中doc.AddMember("education", education, doc.GetAllocator());// 对象包含数组 { [], [] }QList<QList<int>> intList = { { 1, 2 }, { 3, 4 } };// 1.定义空的对象rapidjson::Value number(rapidjson::kObjectType);for (int i = 0; i < intList.count(); ++i) {QList<int> tmpList = intList[i];// 2.定义空的数组rapidjson::Value tmpArr(rapidjson::kArrayType);for (int j = 0; j < tmpList.count(); ++j) {// 3.往数组中插入数据tmpArr.PushBack(tmpList.at(j), doc.GetAllocator());}// 4.数组插入到对象中QString key = QString("num%1").arg(i+1); // 插入到对象中,需要指定key,且不能重名number.AddMember(rapidjson::Value(key.toUtf8().constData(), doc.GetAllocator()),tmpArr, doc.GetAllocator());}// 5.对象包含数组 插入到doc中doc.AddMember("number", number, doc.GetAllocator());// 对象包含对象 { {}, {} }// 1.定义空的对象rapidjson::Value languages(rapidjson::kObjectType);// 2.定义空的子对象,并插入数据rapidjson::Value serialOne(rapidjson::kObjectType);serialOne.AddMember("language", "汉语", doc.GetAllocator());serialOne.AddMember("grade", 10, doc.GetAllocator());rapidjson::Value serialTwo(rapidjson::kObjectType);serialTwo.AddMember("language", "英语", doc.GetAllocator());serialTwo.AddMember("grade", 4, doc.GetAllocator());// 3.对象插入到对象中languages.AddMember("serialOne", serialOne, doc.GetAllocator());languages.AddMember("serialTwo", serialTwo, doc.GetAllocator());// 4.对象包含对象 插入到doc中doc.AddMember("languages", languages, doc.GetAllocator());// 将Document转换为字符串输出rapidjson::StringBuffer buffer;rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 默认带换行和缩进writer.SetFormatOptions(rapidjson::kFormatSingleLineArray); // 格式会紧凑一点点doc.Accept(writer);QByteArray jsonArr = buffer.GetString();qDebug() << QString(jsonArr);// 写入文件writeStrToFile1(JSON_FILE, jsonArr);
}void Widget::parseJson()
{// 读取文件中的json数据QString jsonStr = readFileAllStr(JSON_FILE);qDebug() << jsonStr;// 创建一个 Document 对象rapidjson::Document doc;// 解析 JSON 字符串if (doc.Parse(jsonStr.toUtf8().constData()).HasParseError()) {qWarning() << "JSON 解析错误!";return ;}// 访问 JSON 数据if (doc.HasMember("name") && doc["name"].IsString()) {QString name = doc["name"].GetString();rapidjson::Value name1(doc["name"], doc.GetAllocator());qDebug() << "name = " << name; // 输出有带 " "qDebug() << "name1 = " << name1.GetString(); // 输出没有带 " "}if (doc.HasMember("age") && doc["age"].IsInt()) {int age = doc["age"].GetInt();rapidjson::Value age1(doc["age"], doc.GetAllocator());// 他俩没有区别qDebug() << "age = " << age;qDebug() << "age1 = " << age1.GetInt();}if (doc.HasMember("vip") && doc["vip"].IsBool()) {bool vip = doc["vip"].GetBool();rapidjson::Value vip1(doc["vip"], doc.GetAllocator());// 他俩没有区别qDebug() << "vip = " << vip;qDebug() << "vip1 = " << vip1.GetBool();}if (doc.HasMember("address") && doc["address"].IsNull()) {qDebug() << "address = null";}// 解析 { }if (doc.HasMember("interest") && doc["interest"].IsObject()) {// 1.获得对象
// const rapidjson::Value &interest = doc["interest"].GetObj();rapidjson::Value interest(doc["interest"], doc.GetAllocator());if (interest.IsObject()) {// 2.获得对象内的值if (interest.HasMember("basketball") && interest["basketball"].IsString()) {QString basketball = interest["basketball"].GetString();qDebug() << "basketball = " << basketball;}// 3.另一种方式rapidjson::Value::ConstMemberIterator itr = interest.FindMember("badminton");if (interest.MemberEnd() != itr && interest["badminton"].IsString()) {QString badminton = interest["badminton"].GetString();qDebug() << "badminton = " << badminton;}}}// rapidjson::Value::ConstMemberIterator itr = doc.FindMember("interest");
// if (doc.MemberEnd() != itr) {
// // 1.获得对象const rapidjson::Value &interest = doc["interest"].GetObj();
// rapidjson::Value interest(doc["interest"], doc.GetAllocator());// if (interest.IsObject()) {
// // 2.获得对象内的值
// rapidjson::Value::ConstMemberIterator it = interest.MemberBegin();
// for (; it != interest.MemberEnd(); ++it) {
// QString key = it->name.GetString();
// QString value = it->value.GetString();
// qDebug() << key << " = " << value;
// }
// }
// }// 解析 [ ]
// if (doc.HasMember("color") && doc["color"].IsArray()) {rapidjson::Value::ConstMemberIterator itr = doc.FindMember("color");if (doc.MemberEnd() != itr && doc["color"].IsArray()) {// 1.获得对象
// const rapidjson::Value &color = doc["color"].GetArray();rapidjson::Value color(doc["color"], doc.GetAllocator());if (color.IsArray()) {// 2.数组可通过直接for遍历获取值for (rapidjson::SizeType i = 0; i < color.Size(); ++i) {QString value = color[i].GetString();qDebug() << "value = " << value;}}}// 解析 [ {} ]// 1.查找doc是否有 likerapidjson::Value::ConstMemberIterator itlike = doc.FindMember("like");if (doc.MemberEnd() != itlike && doc["like"].IsArray()) {// 2.获得like数组const rapidjson::Value &like = doc["like"].GetArray();if (like.IsArray()) {// 3.遍历like数组for (rapidjson::SizeType i = 0; i < like.Size(); ++i) {// 4.获得数组内的对象const rapidjson::Value &obj = like[i].GetObj();if (obj.IsObject()) {// 5.获得对象内的值rapidjson::Value::ConstMemberIterator it = obj.MemberBegin();for (; it != obj.MemberEnd(); ++it) {QString key = it->name.GetString();// 6.注意获取值的类型,否则程序会闪退;(所以,一般推荐json的值都使用字符串存储)QString value = it->value.IsString() ? it->value.GetString() : QString::number(it->value.GetDouble());qDebug() << key << " = " << value;}}}}}// 解析 [ [] ]// 1.查找doc是否有 educationrapidjson::Value::ConstMemberIterator iteducation = doc.FindMember("education");if (doc.MemberEnd() != iteducation && doc["education"].IsArray()) {// 2.获得education数组const rapidjson::Value &education = doc["education"].GetArray();if (education.IsArray()) {// 3.遍历education数组for (rapidjson::SizeType i = 0; i < education.Size(); ++i) {// 4.获得数组内的数组const rapidjson::Value &arr = education[i].GetArray();// 5.遍历数组,获得数组内的元素for (rapidjson::SizeType j = 0; j < arr.Size(); ++j) {QString value = arr[j].GetString();qDebug() << "value = " << value;}}}}// 解析 { [] }// 1.查找doc是否有 educationrapidjson::Value::ConstMemberIterator itnumber = doc.FindMember("number");if (doc.MemberEnd() != itnumber && doc["number"].IsObject()) {// 2.获得number对象const rapidjson::Value &number = doc["number"].GetObj();if (number.IsObject()) {// 3.获得对象内的数组rapidjson::Value::ConstMemberIterator itnum1 = number.FindMember("num1");if (number.MemberEnd() != itnum1 && number["num1"].IsArray()) {const rapidjson::Value &num1 = number["num1"].GetArray();if (num1.IsArray()) {// 4.遍历数组获得里面的值for (rapidjson::SizeType i = 0; i < num1.Size(); ++i) {int value = num1[i].GetInt();qDebug() << "value = " << value;}}}rapidjson::Value::ConstMemberIterator itnum2 = number.FindMember("num2");if (number.MemberEnd() != itnum2 && number["num2"].IsArray()) {const rapidjson::Value &num2 = number["num2"].GetArray();for (rapidjson::SizeType i = 0; i < num2.Size(); ++i) {int value = num2[i].GetInt();qDebug() << "value = " << value;}}}}// 解析 { {} }// 1.查找languages对象rapidjson::Value::ConstMemberIterator itLanguages = doc.FindMember("languages");if (doc.MemberEnd() != itLanguages && doc["languages"].IsObject()) {// 2.获得languages对象const rapidjson::Value &languages = doc["languages"].GetObj();// 3.查找serialOne对象rapidjson::Value::ConstMemberIterator itSerialOne = languages.FindMember("serialOne");if (languages.MemberEnd() != itSerialOne && languages["serialOne"].IsObject()) {// 4.获得serialOne对象const rapidjson::Value &serialOne = languages["serialOne"].GetObj();// 5.获得serialOne对象内的值if (serialOne.HasMember("language") && serialOne["language"].IsString()) {QString basketball = serialOne["language"].GetString();qDebug() << "language = " << basketball;}if (serialOne.HasMember("grade") && serialOne["grade"].IsInt()) {int grade = serialOne["grade"].GetInt();qDebug() << "grade = " << grade;}}// 3.查找serialTwo对象rapidjson::Value::ConstMemberIterator itSerialTwo = languages.FindMember("serialTwo");if (languages.MemberEnd() != itSerialTwo && languages["serialTwo"].IsObject()) {// 4.获得serialTwo对象const rapidjson::Value &serialTwo = languages["serialOne"].GetObj();// 5.获得对象内的值rapidjson::Value::ConstMemberIterator it = serialTwo.MemberBegin();for (; it != serialTwo.MemberEnd(); ++it) {QString key = it->name.GetString();// 注意获取值的类型,否则程序会闪退;(所以,一般推荐json的值都使用字符串存储)QString value = it->value.IsString() ? it->value.GetString() : QString::number(it->value.GetInt());qDebug() << key << " = " << value;}}}
}void Widget::modifyJson()
{// 读取文件中的json数据QString jsonStr = readFileAllStr(JSON_FILE);qDebug() << jsonStr;// 创建一个 Document 对象rapidjson::Document doc;// 解析 JSON 字符串if (doc.Parse(jsonStr.toStdString().c_str()).HasParseError()) {qWarning() << "JSON 解析错误!";return ;}// 修改 JSON 数据// 1.判断是否存在(注意,如果不存在,直接修改会报错,所以需要判断是否存在)if (doc.HasMember("name")) {// 2.直接赋值修改即可doc["name"] = "小杨";}if (doc.HasMember("age")) {doc["age"] = 100;}if (doc.HasMember("vip")) {doc["vip"] = true;}if (doc.HasMember("address")) {doc["address"] = "广东省...";}// 修改 { }if (doc.HasMember("interest") && doc["interest"].IsObject()) {// 1.获得对象rapidjson::Value interest(doc["interest"], doc.GetAllocator());// 2.修改对象内的值if (interest.HasMember("basketball")) {interest["basketball"] = "姚明";}// 另一种方式rapidjson::Value::ConstMemberIterator itr = interest.FindMember("badminton");if (interest.MemberEnd() != itr) {interest["badminton"] = "林丹";}// 3.修改完后重新赋值doc["interest"] = interest;}// 修改 [ ] 内的值// 1.查找是否存在数组rapidjson::Value::ConstMemberIterator itColor = doc.FindMember("color");if (doc.MemberEnd() != itColor) {// 2.获得数组rapidjson::Value color(doc["color"], doc.GetAllocator());// 3.准备修改的数据QStringList colorList = { "red", "blue" };// 4.数组可通过直接for遍历修改,也可以单独一个也给去修改,通过下标for (rapidjson::SizeType i = 0; i < color.Size(); ++i) {color[i].SetString(colorList[i].toUtf8().constData(), doc.GetAllocator());
// color[i].Set(colorList[i].toUtf8().constData()); // 也可以使用这个}// 5.修改完后重新赋值doc["color"] = color;}// 修改 [ {} ] 内的值// 1.查找是否存在数组rapidjson::Value::ConstMemberIterator itLike = doc.FindMember("like");if (doc.MemberEnd() != itLike) {// 2.获得数组rapidjson::Value like(doc["like"], doc.GetAllocator());// 3.准备修改的数据QStringList gameList = { "中国象棋", "围棋", "五子棋" };QList<double> priceList = { 77.7, 88.8 , 99.9 };// 4.数组可通过直接for遍历修改,也可以单独一个也给去修改,通过下标for (rapidjson::SizeType i = 0; i < like.Size(); ++i) {// 5.获得数组内的对象rapidjson::Value obj(like[i], doc.GetAllocator());// 修改字符串相关if (obj.HasMember("game")) {obj["game"].SetString(gameList[i].toUtf8().constData(), doc.GetAllocator());
// obj["game"].Set(gameList[i].toUtf8().constData(), doc.GetAllocator());}// 修改整形相关rapidjson::Value::ConstMemberIterator itr = obj.FindMember("price");if (obj.MemberEnd() != itr) {obj["price"] = priceList[i];}like[i] = obj;}// 5.修改完后重新赋值doc["like"] = like;}// 修改 [ [] ] 内的值// 1.查找是否存在数组rapidjson::Value::ConstMemberIterator itEducation = doc.FindMember("education");if (doc.MemberEnd() != itEducation) {// 2.获得数组rapidjson::Value education(doc["education"], doc.GetAllocator());// 可以使用数组方式去修改
// education[0][0] = "小学六年级";
// education[0][1] = "初中初三";
// education[1][0] = "高中高三";
// education[1][1] = "大学大四";// 3.准备修改的数据QList<QList<QString>> list = { { "小学六年级", "初中初三" }, { "高中高三", "大学大四" } };// 4.数组可通过直接for遍历修改,也可以单独一个也给去修改,通过下标for (rapidjson::SizeType i = 0; i < education.Size(); ++i) {// 5.获得数组内的数组rapidjson::Value arr(education[i], doc.GetAllocator());for (rapidjson::SizeType j = 0; j < arr.Size(); ++j) {// 修改值arr[j].SetString(list[i][j].toUtf8().constData(), doc.GetAllocator());
// arr[j].Set(list[i][j].toUtf8().constData(), doc.GetAllocator());}// 重新赋值education[i] = arr;}// 6.修改完后重新赋值doc["education"] = education;}// 修改 { [] } 内的值// 1.查找是否存在对象rapidjson::Value::ConstMemberIterator itNumber = doc.FindMember("number");if (doc.MemberEnd() != itNumber) {rapidjson::Value number(doc["number"], doc.GetAllocator());// 2.获得对象内的数组rapidjson::Value num1(number["num1"], doc.GetAllocator());for (rapidjson::SizeType i = 0; i < num1.Size(); ++i) {num1[i] = num1[i].GetInt() + 10;}rapidjson::Value num2(number["num2"], doc.GetAllocator());for (rapidjson::SizeType i = 0; i < num2.Size(); ++i) {num2[i] = num2[i].GetInt() + 10;}// 3.重新在赋值回来number["num1"] = num1;number["num2"] = num2;doc["number"] = number;}// 修改 { { } } 内的值// 1.查找是否存在对象rapidjson::Value::ConstMemberIterator itLanguages = doc.FindMember("languages");if (doc.MemberEnd() != itLanguages) {rapidjson::Value languages(doc["languages"], doc.GetAllocator());// 2.获得对象内的对象rapidjson::Value serialOne(languages["serialOne"], doc.GetAllocator());serialOne["language"].SetString("粤语", doc.GetAllocator());serialOne["grade"].SetInt(9);rapidjson::Value serialTwo(languages["serialTwo"], doc.GetAllocator());serialTwo["language"].SetString("白话", doc.GetAllocator());serialTwo["grade"].SetInt(8);// 3.重新在赋值回来languages["serialOne"] = serialOne;languages["serialTwo"] = serialTwo;doc["languages"] = languages;}// 将Document转换为字符串输出rapidjson::StringBuffer buffer;rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 默认带换行和缩进writer.SetFormatOptions(rapidjson::kFormatSingleLineArray); // 格式会紧凑一点点doc.Accept(writer);QByteArray jsonArr = buffer.GetString();qDebug() << QString(jsonArr);// 写入文件writeStrToFile1(JSON_FILE, jsonArr);
}void Widget::deleteJson()
{// 读取文件中的json数据QString jsonStr = readFileAllStr(JSON_FILE);qDebug() << jsonStr;// 创建一个 Document 对象rapidjson::Document doc;// 解析 JSON 字符串if (doc.Parse(jsonStr.toStdString().c_str()).HasParseError()) {qWarning() << "JSON 解析错误!";return ;}// 删除 JSON 数据// 1.直接删除即可doc.RemoveMember("name");doc.RemoveMember("age");doc.RemoveMember("vip");doc.RemoveMember("address");// 删除 { } 中的值// 1.查找是否有对象if (doc.HasMember("interest") && doc["interest"].IsObject()) {// 2.获得对象rapidjson::Value interest(doc["interest"], doc.GetAllocator());// 3.删除对象内的值interest.RemoveMember("badminton");// 4.删除完后重新赋值doc["interest"] = interest;}// 删除 [ ] 内的值// 1.查找是否存在数组rapidjson::Value::ConstMemberIterator itColor = doc.FindMember("color");if (doc.MemberEnd() != itColor) {// 2.获得数组rapidjson::Value color(doc["color"], doc.GetAllocator());// 3.根据下表删除color.Erase(color.Begin() + 1); // 删除索引1的元素(第二个元素)//doc.RemoveMember("color"); // 删除键为"color"的整个数组//color.Clear(); // 清空数组,结果为"color":[]// 4.修改完后重新赋值doc["color"] = color;}// 删除 [ {} ] 内的值// 1.查找是否存在数组rapidjson::Value::ConstMemberIterator itLike = doc.FindMember("like");if (doc.MemberEnd() != itLike) {// 2.获得数组rapidjson::Value like(doc["like"], doc.GetAllocator());// 3.根据下表删除like.Erase(like.Begin() + 1); // 删除索引1的元素(第二个元素)// 4.修改完后重新赋值doc["like"] = like;}// 删除 [ [] ] 内的值// 1.查找是否存在数组rapidjson::Value::ConstMemberIterator itEducation = doc.FindMember("education");if (doc.MemberEnd() != itEducation) {// 2.获得数组rapidjson::Value education(doc["education"], doc.GetAllocator());// 3.根据下表删除education.Erase(education.Begin() + 1); // 删除索引1的元素(第二个元素)// 4.修改完后重新赋值doc["education"] = education;}// 删除 { [] } 内的值// 1.查找是否存在对象rapidjson::Value::ConstMemberIterator itNumber = doc.FindMember("number");if (doc.MemberEnd() != itNumber) {rapidjson::Value number(doc["number"], doc.GetAllocator());// 删除对象内的值number.RemoveMember("num2");doc["number"] = number;}// 删除 { { } } 内的值// 1.查找是否存在对象rapidjson::Value::ConstMemberIterator itLanguages = doc.FindMember("languages");if (doc.MemberEnd() != itLanguages) {rapidjson::Value languages(doc["languages"], doc.GetAllocator());// 删除对象内的值languages.RemoveMember("serialOne");doc["languages"] = languages;}// 将Document转换为字符串输出rapidjson::StringBuffer buffer;rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 默认带换行和缩进writer.SetFormatOptions(rapidjson::kFormatSingleLineArray); // 格式会紧凑一点点doc.Accept(writer);QByteArray jsonArr = buffer.GetString();qDebug() << QString(jsonArr);// 写入文件writeStrToFile1(JSON_FILE, jsonArr);
}bool Widget::writeStrToFile(const QString &fileNmae, const QByteArray &data)
{QFile file(fileNmae);if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {qDebug() << "文件打开失败!" << fileNmae;return false;}const int chunkSize = 8192; // 每次写入文件的大小QTextStream out(&file);int totalSize = data.size();int writtenSize = 0;qDebug() <<"文件大小 = " << (totalSize / 1024.0) << "KB";while (writtenSize < totalSize) {// 计算当前块的起始位置和大小int currentChunkSize = qMin(chunkSize, totalSize - writtenSize);QString chunk = data.mid(writtenSize, currentChunkSize);QByteArray utf8Chunk = chunk.toUtf8();// 写入当前块out << utf8Chunk;writtenSize += currentChunkSize;if (0 == writtenSize % 10) {// 刷新缓冲区out.flush();}}out.flush();file.close();qDebug() << "写入完成!";return true;
}bool Widget::writeStrToFile1(const QString &fileName, const QByteArray &data)
{QFile file(fileName);if (file.open(QIODevice::WriteOnly)) {file.write(data);} else {return false;}file.close();return true;
}QByteArray Widget::readFileAllByte(const QString &fileName)
{QByteArray byteArray = QByteArray();QFile file2(fileName);if (file2.open(QIODevice::ReadOnly | QIODevice::Text)) {qint64 size = file2.size();byteArray.resize(size);byteArray = file2.readAll();file2.close();}return byteArray;
}QString Widget::readFileAllStr(const QString &fileName)
{QString str = nullptr;QFile file2(fileName);if (file2.open(QIODevice::ReadOnly | QIODevice::Text)) {QTextStream in(&file2);in.setCodec("UTF-8");str = in.readAll();file2.close();}return str;
}
七、总结
在做项目中遇到问题,通过网上了解,往某个方向可以解决,然后自己去学习如何处理,问题解决后,将相关知识点记录下来,分享!
最后,此文章只是记录rapidjson库的一部分操作,如需深入学习,还请移步官方文档;
程序员要养好看文档的习惯。