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_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库的一部分操作,如需深入学习,还请移步官方文档

程序员要养好看文档的习惯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cpp_learners

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

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

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

打赏作者

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

抵扣说明:

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

余额充值