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

轻松上手 C++ 的 RapidJSON 解析库:从零开始的教程 RapidJSON 是一个高性能、轻量级的 JSON 解析库,专为 C++ 设计。高性能:RapidJSON 的解析速度非常快,几乎可以与strlen()函数的速度相媲美。易用性:RapidJSON 提供了简洁的 API,使得解析和生成 JSON 数据变得非常简单。灵活性:支持多种数据类型,包括对象、数组、字符串、数字、布尔值和 NULL。跨平台:支持 Windows、Linux、macOS 等多种操作系统。在访问 JSON 数据之前,最好先检查成员是否存在,以避免程序崩溃。可以使用HasMember。 阅读详情
AI摘要

本文介绍了C++的rapidjson库,它是腾讯开源的JSON解析器及生成器,跨平台且能处理超100mb的JSON数据,解决了QT自带JSON库处理大文件的限制问题。详细讲解了使用该库对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库的一部分操作,如需深入学习,还请移步官方文档;

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

RapidJSON入门:手把手教入门实例介绍 RapidJSON优点 跨平台 编译器:Visual Studio、gcc、clang 等 架构:x86、x64、ARM 等 操作系统:Windows、Mac OS X、Linux、iOS、Android 等 容易安装 只有头文件的库。只需把头文件复制至你的项目中。 独立、最小依赖 不需依赖 STL、BOOST 等。 只包含 <cstdio>, <cstdlib>, <cstring>, <inttypes.h>, <new>, &. 阅读详情

相关推荐

C++ JSON库libjson:轻量高效的跨平台数据解析方案

JSON作为一种轻量级的数据交换格式,在现代软件开发中广泛应用于网络通信、配置文件和API交互等场景。其基于文本、易于阅读和编写的特性,使其成为跨语言数据交换的事实标准。在C++生态中,由于标准库长期缺乏原生JSON支持,开发者通常需要借助第三方库来实现高效的序列化与反序列化。libjson正是这样一个专注于性能与资源效率的C++ JSON解析库,它通过纯粹的C++实现和RAII内存管理,在解析速度和内存占用之间取得了良好平衡。该库特别适合对性能敏感或资源受限的嵌入式环境,其直观的API设计和出色的跨平台能

diejiankuai3444的博客 436

RapidJSON简介及使用

RapidJSON是腾讯开源的一个高效的C++ JSON解析器及生成器,它是只有头文件的C++库

网络资源是无限的 8万+

c++与golang操作数据库总结【c++与golang】

C++和Go语言都可以通过第三方库或内置的库来连接到不同类型的数据库,并且在连接成功后可以使用SQL语句对数据进行操作。分析两种语言对数据库的操作异同点有助于学习两种语言的优劣之处:通过比较这两门语言在处理数据库方面的能力和性能,我们可以更好地理解它们各自的优点和缺点,了解它们在不同情况下的适用性。提高跨平台开发的能力:由于C++和Go语言都是跨平台的编程语言,因此比较它们在数据库操作方面的异同点,可以帮助我们更好地了解如何在不同的操作系统和硬件平台上进行开发,提高跨平台开发的能力。

weixin_44545838的博客 1675

RapidJSON介绍

RapidJSON 是一个 C++ 的 JSON 解析库,由腾讯开源。支持 SAX 和 DOM 风格的 API,并且可以解析、生成和查询 JSON 数据。RapidJSON 快。它的性能可与strlen() 相比。可支持 SSE2/SSE4.2 加速。RapidJSON 独立。它不依赖于 BOOST 等外部库。它甚至不依赖于STL。RapidJSON 对内存友好。在大部分 32/64 位机器上,每个 JSON 值只占 16字节(除字符串外)。

希望能帮助大家,希望大家多多支持,你们的支持是我前进的动力。 3362

C++ JSON处理实战:jsoncpp集成、中文乱码解决与性能优化指南

JSON作为一种轻量级的数据交换格式,在现代软件开发中扮演着至关重要的角色,尤其在配置管理、网络通信和API交互等场景。其核心原理是基于文本的、独立于语言的数据表示法,易于人阅读和编写,也易于机器解析和生成。在C++生态中,处理JSON数据需要借助专门的库来实现序列化与反序列化,这直接关系到程序的健壮性和开发效率。jsoncpp作为一个历史悠久、稳定可靠的C++ JSON库,其技术价值在于提供了简单直观的API和出色的跨平台兼容性,非常适合用于企业级应用、嵌入式系统以及对稳定性要求极高的遗留项目维护。通过掌

weixin_33861800的博客 366

C++跨语言电子病历编辑器:高性能核心与多端集成架构解析

在软件架构设计中,跨语言互操作性是一个基础且关键的技术概念,它允许不同编程语言编写的模块高效协同工作。其核心原理在于定义清晰的接口规范和内存管理机制,通过C API、SWIG或现代绑定库等技术桥接语言差异。这项技术的价值在于能够充分发挥各语言生态的优势,例如利用C++实现高性能计算核心,同时通过Python或JavaScript快速构建上层应用和界面。在医疗信息化、科学计算、游戏引擎等对性能和集成度要求高的应用场景中,跨语言架构尤为重要。本文聚焦于电子病历编辑器这一具体领域,深入探讨了如何基于C++构建高性

weixin_30600197的博客 373

Python生态JSON处理库:json、orjson、ujson、simplejson、python-rapidjson、json5、jsonpatch

Python生态JSON处理库:json、orjson、ujson、simplejson、python-rapidjson、json5、jsonpatch

lonelymanontheway的博客 203

RK3588平台rkaiq_3A_server JSON配置解析失败根因与修复指南

JSON配置是嵌入式视觉系统中连接算法与硬件的关键接口,其解析原理涉及字符编码、语法子集、类型校验与系统权限等多层机制。在RK3588等ARM SoC平台上,rkaiq_3A_server采用定制轻量解析器,对BOM头、换行符、注释、键名大小写及数值类型高度敏感,导致‘parse failed’错误频发。这类问题本质并非JSON语法错误,而是嵌入式环境约束与开发习惯错配所致,直接影响自动曝光、白平衡和对焦等3A功能稳定性。典型应用场景包括工业相机固件集成、YOLOv8图像预处理校准及边缘RTSP流质量保障。

weixin_34208283的博客 344

nlohmann/json库:现代C++ JSON处理从入门到实战

JSON作为一种轻量级数据交换格式,在Web API、配置管理和数据持久化等场景中广泛应用。其核心原理是基于文本的键值对与数组结构,易于人类阅读和机器解析。在C++生态中,高效处理JSON数据对提升开发效率和系统性能至关重要。nlohmann/json库通过头文件实现和直观的API设计,显著降低了集成与使用门槛,实现了易用性与性能的平衡。该库支持动态类型操作、安全的数据访问模式,以及无缝的STL容器与自定义类型转换,极大简化了序列化与反序列化流程。在工程实践中,它广泛应用于配置文件读写、网络通信数据解析和日

weixin_30425949的博客 437

C++课程设计实战:面向对象与文件I/O实现杂志订阅管理系统

面向对象程序设计(OOP)是软件工程的核心思想,通过封装、继承和多态三大特性,将现实世界实体抽象为类与对象,构建模块化、可复用的代码结构。其原理在于将数据与操作数据的方法绑定,实现高内聚低耦合的设计。在工程实践中,结合数据结构(如STL容器)与文件I/O操作,能够将内存中的对象持久化存储,这是构建桌面应用与管理系统的基础能力。本文以经典的“杂志订阅管理系统”为例,深入解析如何运用C++的类设计、STL容器(map/vector)管理数据,并通过自定义文本格式实现健壮的文件存储,为课程设计及中小型CRUD系统

weixin_33735077的博客 520

C++ RapidJSON使用详解

RapidJSON主页:RapidJSON 是由腾讯开发的一个 C++ 的 JSON 解析器及生成器,它的灵感来自 RapidXml。

琅嬛福地 2088

Qt JSON详解二

JSON( JavaScript Object Notation,对象表示法) 是一种轻量级的数据交换格式。它基于 ECMAScript 的一个子集。许多编程语言都很容易找到J SON 解析器和 JSON 库。JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。不同语言的不同 json 库对 JSON 标准的支持不尽相同,为了能让尽可能多的 JSON 库都能正常解析和生成 JSON ,定义 JSON 的规范很重要,推荐一个 JSON 规范《Google - JSON风格指南。

m0_73482095的博客 1015

RapidJSON动态解析实战:零拷贝与内存池优化技巧

JSON作为轻量级数据交换格式,在C++后端服务中无处不在,其解析效率直接影响系统吞吐。RapidJSON凭借零拷贝解析和内存池分配机制,成为高并发场景下的热门选择。它的核心设计在于直接引用输入缓冲区,减少不必要的数据复制,同时通过分块内存池统一管理节点生命周期,从而在保持极致性能的同时提供完整的动态DOM操作能力。无论是配置中心的数据下发、协议拆解还是通用网关处理,RapidJSON都能在毫秒级完成任意结构的JSON读写。对于需要频繁处理JSON的高性能服务,掌握其类型安全判断、生命周期管理及性能调优手段

weixin_29248611的博客 173

C++ JSON-RPC实战:从开源库选型到生产环境避坑指南

远程过程调用(RPC)是分布式系统实现跨进程、跨网络通信的核心技术,它通过封装网络通信细节,使开发者能够像调用本地函数一样调用远程服务。JSON-RPC作为一种基于JSON的轻量级RPC协议,因其文本格式、跨语言和易于调试的特性,在微服务架构和前后端交互中广泛应用。其技术价值在于简化了异构系统间的集成,降低了通信层的开发复杂度。在C++工程实践中,集成JSON-RPC常面临开源库选型、线程模型设计、自定义类型序列化及生产环境稳定性等挑战。本文聚焦于jsonrpccxx、libjson-rpc-cpp等主流C

weixin_30855099的博客 438

告别卡顿!用U盘给你的MacBook Pro 2015+来一次macOS Monterey的‘大扫除’式安装

每次系统升级后,老款MacBook Pro用户最常抱怨的就是"怎么比之前更卡了?"——这不是错觉。系统迭代过程中积累的缓存文件、残留配置和隐形服务,就像房间角落堆积的灰尘,拖慢了整台机器的响应速度。而通过U盘进行的macOS Monterey全新安装,本质上是一次彻底的"数字大扫除":它不仅替换系统文件,还会重建所有索引、清理磁盘碎片,甚至能解决某些玄学般的卡顿问题。对于2015款及之后的MacBook Pro用户,这种安装方式能让老设备重获新生。

weixin_28731223的博客 309

Linux系统下奥比中光Astra Pro相机SDK部署与避坑指南

本文详细指导了在Linux系统下部署奥比中光Astra Pro深度相机SDK的全过程,涵盖系统准备、SDK安装、设备权限配置及常见问题排查。重点解析了USB设备规则配置这一关键步骤,并提供了Python与C++项目的集成方法,旨在帮助开发者快速完成相机配置,避免常见陷阱。

weixin_28455801的博客 298

HuJSON(JWCC)格式详解:带注释与尾随逗号的 JSON 扩展及其 Go 解析实现

HuJSON("Human JSON",人类友好 JSON)是对标准 JSON(RFC 8259)的扩展,核心目标是把 JSON 变成更适合人手编写与维护的配置文件格式。本篇文章以 Sliver(Adversary Emulation Framework)仓库中 vendored 的 `github.com/tailscale/hujson` 包为对象,完整讲解 JWCC 语法、Go 语言中的解析

gitblog_00480的博客 431

B站李沐讲论文笔记AlexNet

B站李沐讲论文笔记AlexNet

夏知识不进脑子薇的博客 789

现代C++配置管理:TOML++库从入门到工程实践

在软件工程中,配置管理是连接代码逻辑与运行时行为的关键环节。其核心原理在于将可变参数从硬编码中解耦,通过外部文件或数据源进行动态控制,从而提升系统的灵活性和可维护性。传统方案如JSON或XML虽应用广泛,但在可读性、严格性和易用性上常面临挑战。TOML(Tom's Obvious, Minimal Language)作为一种新兴的配置文件格式,以其类似INI的直观语法和严格的类型系统脱颖而出,成为现代应用配置的热门选择。其技术价值在于显著提升了配置文件的编写与阅读体验,并减少了因格式歧义导致的解析错误。在C

444

Win11移动热点连接故障排查:从IP配置失败到网络共享的全面解决指南

本文提供了Win11移动热点连接故障的全面排查指南,重点解决手机连接时卡在“获取IP地址”或提示“IP配置失败”的问题。文章从基础检查(如确认网络连接、选择正确共享源)入手,深入讲解了核心的网络适配器共享设置、关键系统服务检查、防火墙配置以及终极解决方案——网络重置。通过系统性的步骤,帮助用户彻底修复Win11移动热点无法共享网络的问题。

alice7model的博客 784

从踩坑到填平:我在RHEL7上给Tesla A100装驱动的完整记录(含Fabric Manager配置)

本文详细记录了在RHEL7系统上为Tesla A100安装Nvidia驱动的完整过程,包括Fabric Manager配置的关键步骤。通过分析A100架构的特殊性,提供了从驱动安装到服务配置的详细指南,并分享了常见问题的排查方法和性能调优技巧,帮助用户高效部署高性能GPU计算环境。

weixin_29291863的博客 282

艾尔登法环存档怎么改:ER-Save-Editor 属性装备修改实操

在《艾尔登法环》里把属性点加错、错过的传说装备又不想重开档,是不少褪色者都踩过的坑。ER-Save-Editor 是一款开源的艾尔登法环存档编辑器,直接读写 PC 和 PlayStation 的存档文件,能帮你调属性、往背包塞装备、解锁区域和事件,不用推倒重玩。 ## 能帮你解决什么 - 想调整 Build 属性 → 在 Stats 页直接改八项数值,HP/FP/SP 与等级自动重算 - 想补

gitblog_00023的博客 771

单稳态触发器Multisim电路仿真——硬件工程师笔记

本文系统介绍了单稳态触发器的基础知识及其实现方式。主要内容包括:1)单稳态触发器的工作原理、电路结构、特点及应用;2)555定时器实现单稳态触发器的配置及工作过程;3)使用反相器和与非门实现积分型和微分型单稳态触发器的电路结构及工作原理。文章详细阐述了各种实现方式的特性、应用场景及设计考虑,为硬件工程师提供了实用的电路设计参考。最后还附有相关笔试面试题链接,便于读者进一步学习扩展。

XU157303764的博客 1875

C++实战:古城景区管理系统设计与实现,涵盖票务、客流监控与数据持久化

面向对象编程(OOP)是现代软件开发的基石,其核心思想是通过封装、继承和多态来模拟现实世界,构建模块化、可复用的代码结构。在C++这类系统级语言中,OOP与标准模板库(STL)的结合,能高效管理复杂数据结构和业务逻辑。这种技术组合在需要高性能和精细资源控制的场景中价值显著,例如物联网设备集成、实时数据处理和后台管理系统开发。本文以【古城景区管理系统】为具体案例,深入探讨了如何运用C++11特性、Qt框架以及JSON序列化,实现从票务管理、实时客流监控到数据持久化的完整业务闭环,为C++工程实践提供了详实的参

chutisun0039的博客 413

【PyTorch深度学习项目实战100例目录】项目详解 + 数据集 + 完整源码

大家好,我是阿光。本专栏整理了《深度学习100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。正在更新中~ ✨。

优快云 精品推荐 10万+

【嵌入式DIY实例ESP32篇】-步数计数器

在本项目中,我们将使用 ESP32 微控制器和博世的 BMI160 加速度计陀螺仪模块构建一款便携式计步器

视觉与物联智能 801
上一篇: QT 自定义ComboBox,实现下拉框文本颜色设置
下一篇: QT 日志 - qInstallMessageHandler将qDebug()打印内容输出到文件
cpp_learners
博客等级 码龄7年 1526粉丝 274原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

cpp_learners

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

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

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

打赏作者

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

抵扣说明:

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

余额充值