c++ 使用rapidjson对数据序列化和反序列化(vs2109)

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

  1. 安装

在NuGet中为项目安装tencent.rapidjson

  1. 引用头文件

#include <rapidjson/document.h>

#include <rapidjson/memorystream.h>

#include <rapidjson/prettywriter.h>

  1. 头文件定义

添加测试json字符串和类型对应数组

复制代码
// 测试json字符串
const char* strJson = "{\"name\":\"MenAngel\",\"age\":23,\"hobbys\":[\"语文\",\"数学\",\"英语\",54],\"scores\":{\"数学\":\"90.6\",\"英语\":\"100.0\", \"语文\":\"80.0\"}}";

// 数据类型,和 rapidjson的enum Type 相对应
static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
  1. 修改JSON 内容

    ///


    /// 修改JSON 内容
    ///

    void MyRapidJson::alterJson()
    {
    rapidjson::Document doc;
    doc.Parse(strJson);
    cout << "修改前: " << strJson <<"\n" << endl;

    复制代码
     // 修改内容
    
     rapidjson::Value::MemberIterator iter = doc.FindMember("name");
     if (iter != doc.MemberEnd())
         doc["name"] = "张三";
    
     iter = doc.FindMember("age");
     if (iter != doc.MemberEnd())
     {
         rapidjson::Value& v1 = iter->value;
         v1 = "40";
     }
    
     // 修改后的内容写入 StringBuffer 中
     rapidjson::StringBuffer buffer;
     rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
     doc.Accept(writer);
    
     cout <<"修改后: " << buffer.GetString() << "\n" << endl;

    }

运行结果:

{"name":"张三","age":"40","hobbys":"语文","数学","英语",54,"scores":{"数学":"90.6","英语":"100.0","语文":"80.0"}}

  1. 生成 json 数据

    ///


    /// 生成JSON数据
    ///

    void MyRapidJson::createJson()
    {
    // 1.准备数据
    string name = "王五";
    string gender = "boy";
    int age = 23;
    bool student = true;
    vector hobbys = { "语文","数学","英语" };
    map<string, double> scores = { {"语文",80},{"数学",90},{"英语",100} };

    复制代码
     //2.初始化DOM
     rapidjson::Document doc;
     rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
     doc.SetObject();
    
     // 添加数据
     /* 字符串添加 */ 
     rapidjson::Value tempValue1;
     tempValue1.SetString(name.c_str(), allocator);
     doc.AddMember("name", tempValue1, allocator);
    
     rapidjson::Value tempValue2(rapidjson::kStringType);
     tempValue2.SetString(gender.c_str(), allocator);
     doc.AddMember(rapidjson::StringRef("gender"), tempValue2, allocator);
    
     /* 数字类型添加 */
     doc.AddMember("age", age, allocator);
    
     /* bool 类型 */
     rapidjson::Value tempValueStu(rapidjson::kTrueType);
     tempValueStu.SetBool(student);
     doc.AddMember(rapidjson::StringRef("student"), tempValueStu, allocator);
    
     /* Array 添加数据 */
     rapidjson::Value tempValue3(rapidjson::kArrayType);
     for (auto hobby : hobbys)
     {
         rapidjson::Value hobbyValue(rapidjson::kStringType);
         hobbyValue.SetString(hobby.c_str(), allocator);
         tempValue3.PushBack(hobbyValue, allocator);
     }
     doc.AddMember("hobbys", tempValue3, allocator);
    
     /* Object 添加 */
     rapidjson::Value tempValue4(rapidjson::kObjectType);
     tempValue4.SetObject();
     for (auto score : scores)
     {
     	//rapidjson::Value scoreName(rapidjson::kStringType);
     	//scoreName.SetString(score.first.c_str(), allocator);
     	//tempValue4.AddMember(scoreName, score.second, allocator);
    
         // 方法二
     	rapidjson::Value scoreName(rapidjson::kStringType);
     	scoreName.SetString(score.first.c_str(), allocator);
    
     	rapidjson::Value scoreValue(rapidjson::kStringType);
         char charValue[20];
         itoa(score.second, charValue,10);
     	scoreValue.SetString(charValue, allocator);
     	tempValue4.AddMember(scoreName, scoreValue, allocator);
     }
     doc.AddMember("scores", tempValue4, allocator);
    
     // 写入 StringBuffer
     rapidjson::StringBuffer strBuffer;
     rapidjson::Writer<rapidjson::StringBuffer> writer(strBuffer);
     doc.Accept(writer);
    
     cout << strBuffer.GetString() << "\n" << endl;
    
     string outFileName = "C:\\Users\\Administrator\\Desktop\\creatJson.txt";
     ofstream outfile(outFileName, std::ios::trunc);
     outfile << strBuffer.GetString() << endl;
     outfile.flush();
     outfile.close(); 

    }

运行结果:

{"name":"王五","gender":"boy","age":23,"student":true,"hobbys":"语文","数学","英语","scores":{"数学":"90","英语":"100","语文":"80"}}

  1. json 数据解析

    ///


    /// 查询json 内容
    ///

    void MyRapidJson::searchJson()
    {
    rapidjson::Document doc;
    if (doc.Parse(strJson).HasParseError())
    {
    std::cout << "json 解析错误" << std::endl;
    return;
    }

    复制代码
     cout << "doc 的属性成员有 " << doc.MemberCount() << "个!" << endl;
    
     vector<string> propertyName;
     int i = 0;
     for (rapidjson::Value::MemberIterator iter = doc.MemberBegin(); iter != doc.MemberEnd(); ++iter)
     {
         cout << ++i << "、 " << iter->name.GetString() << "    is " << kTypeNames[iter->value.GetType()] << endl;
         propertyName.push_back(iter->name.GetString());
     }
     cout << endl;
    
     for (rapidjson::Value::MemberIterator iter = doc.MemberBegin(); iter != doc.MemberEnd(); ++iter)
     {
         if (iter->value.GetType() == rapidjson::kObjectType || iter->value.GetType() == rapidjson::kArrayType)
             cout << iter->name.GetString() << " : " << endl;
         else 
             cout << iter->name.GetString() << " : ";
    
         DfsDocument(std::move(iter->value));
     }

    }

    ///


    /// 遍历里面的内容
    ///

    ///
    void MyRapidJson::DfsDocument(rapidjson::Value val)
    {
    if (!val.GetType())
    return;

    复制代码
     switch (val.GetType()) {
     case rapidjson::kNumberType:
     	cout << val.GetInt() << endl;
     	break;
     case rapidjson::kStringType:
     	cout << val.GetString() << endl;
     	break;
     case rapidjson::kArrayType:
     	for (rapidjson::Value::ValueIterator itr = val.GetArray().begin();
     		itr != val.GetArray().end(); ++itr) {
     		rapidjson::Value a;
     		a = *itr;
     		DfsDocument(std::move(a));
     	}
     	break;
     case rapidjson::kObjectType:
     	for (rapidjson::Value::MemberIterator itr = val.GetObject().begin();
     		itr != val.GetObject().end(); ++itr) {
     		cout << itr->name.GetString() << " ";
     		rapidjson::Value a;
     		a = itr->value;
     		DfsDocument(std::move(a));
     	}
     default:
     	break;
     }

    }

运行结果

这里需要注意:

object 类型json字符串中,"数字类型" 需转为 "字符串",否则查询时会报错。

  1. rapidjson 的其他使用方法

    ///


    /// json 属性
    ///

    void MyRapidJson::JsonAttribute()
    {
    rapidjson::Document doc;
    if (doc.Parse(strJson).HasParseError())
    {
    std::cout << "json 解析错误" << std::endl;
    return;
    }

    复制代码
     // 成员判断
     if (doc.HasMember("hobbys") && !doc["hobbys"].Empty())
         cout << "doc[\"hobbys\"] is not empty!" << "\n" << endl;
     else
         cout << "doc[\"hobbys\"] 不存在。" << "\n" << endl;
    
     //7.Array的大小
     if (doc["hobbys"].IsArray())
     {
         cout << "doc[\"hobbys\"].Capacity() =  \"  Array的容量及大小:\" " << doc["hobbys"].Capacity() << " 项" << endl;
         cout << "doc[\"hobbys\"].Size() =  \"  Array的容量及大小:\" " << doc["hobbys"].Size() << " 项" << endl;
     }
    
    
     // 字符串长度获取
     cout << doc["name"].GetString()  <<"  字符串长度 :" << doc["name"].GetStringLength() << endl;
    
     //4.查询某个成员是否存在
     rapidjson::Value::MemberIterator iter = doc.FindMember("scores");
     if (iter != doc.MemberEnd())
     {
         cout << iter->name.GetString() << " : " << endl;
         DfsDocument(std::move(iter->value));
     }
     else
         cout << "Not Finded!" << endl;
    
     // 相同判断
     if (doc["name"].GetString() == string("MenAngel") &&
         doc["name"] == "MenAngel" && 
         strcmp(doc["name"].GetString(),"MenAngel") == 0)
     {
         cout << "判断为相等" << endl;
     }

    }

运行结果:

相关推荐
2601_9628857223 分钟前
如何用 Python 做股价历史分位选股?(筛出处于历史低位的股票)
开发语言·python
殷色玫瑰1 小时前
C++入门基础复习:从命名空间到引用与nullptr,一篇重新捡回C++基础
java·开发语言·c++
(Charon)1 小时前
【C++面试】手写线程池:任务队列、工作线程与优雅退出
开发语言·c++
言乐61 小时前
Python概括后端原理
开发语言·python·django·virtualenv·pygame
无名猿1 小时前
拷贝构造与拷贝赋值:调用时机、深浅拷贝与复制消除
c++·内存管理·现代c++·踩坑记录
@大迁世界2 小时前
JEV RAG:更高效的 RAG 系统解决方案?
开发语言·rust
朝朝辞暮i2 小时前
C++ 第一阶段总结:从零基础到 ROS2 前置语法
开发语言·c++·算法
朝朝辞暮i2 小时前
C++ 第 25 课:getter / setter + this
java·javascript·c++
2601_962885722 小时前
如何用 Python 回测定投策略(定期定额 DCA)?(和一次性买入对比)
开发语言·人工智能·python
周杰偷奶茶3 小时前
【JavaSE】类和对象基础
java·开发语言