目录
一、前言
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官方文档!
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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
/// 创建json
void createJson();
/// 解析json
void parseJson();
/// 修改json
void modifyJson();
/// 删除json
void 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 = 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());
/*
//! Type of JSON value
enum Type {
kNullType = 0, //!< null
kFalseType = 1, //!< false
kTrueType = 2, //!< true
kObjectType = 3, //!< object
kArrayType = 4, //!< array
kStringType = 5, //!< string
kNumberType = 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是否有 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;
}
}
}
}
}
// 解析 [ [] ]
// 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;
}
}
}
}
// 解析 { [] }
// 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;
}
}
}
}
// 解析 { {} }
// 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库的一部分操作,如需深入学习,还请移步官方文档;
程序员要养好看文档的习惯。