使用rapidJson C++库生成JSON字符串
- 2020 年 3 月 4 日
- 筆記
前言
RapidJSON 是一个 C++ 的 JSON 解析器及生成器,它是腾讯公司开发的一款高效的 C++ JSON 解析/生成器,提供 SAX 及 DOM 风格 API,中文官网地址为:http://rapidjson.org/zh-cn/,从这里可以看到它的详细说明文档;对应的Github地址为:https://github.com/Tencent/rapidjson,从rapidjson-github上面获取它的最新的源代码,然后把include目录下的rapidjson目录放在自己指定项目下或者自己项目工程对应的include等目录下,使用时包含rapid目录下对应的头文件就可以了,无需编译成静态库文件。它的灵感来自 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”(空字符)。
可以在Linux发行版CentOS7下使用git clone https://github.com/Tencent/rapidjson命令从github上面下载对应的rapidjson的最新代码,以下是我在我的腾讯云主机上下载rapidjson的代码,以及rapidjson项目的目录结构,如下图所示:

从上图rapidjson项目的目录中可以看出,include文件包含的rapidjson文件就是我们使用rapidjson进行json字符串操作时所需要引入的头文件,example是一些代码示例,可供参考。
运行官方的simpledom.cpp示例程序
// simpledom.cpp
// JSON simple example // This example does not handle errors. #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include <iostream> using namespace rapidjson; int main() { // 1. Parse a JSON string into DOM. const char* json = "{"project":"rapidjson","stars":10}"; Document d; d.Parse(json); // 2. Modify it by DOM. Value& s = d["stars"]; s.SetInt(s.GetInt() + 1); // 3. Stringify the DOM StringBuffer buffer; Writer<StringBuffer> writer(buffer); d.Accept(writer); // Output {"project":"rapidjson","stars":11} std::cout << buffer.GetString() << std::endl; return 0; }
在我的腾讯云CentOs7.5主机上的运行截图如下:

应用场景
之前使用过rapidjson读取过激光雷达的数据,最近在实际C++项目开发过程中需要将从设备客户端发送的HJ212报警数据解析后生成指定的JSON格式,如下所示:
{ "Stcode": "SS1311054", "Timestamp": "2020-02-26 13:50:41", "Alarm": [{ "paramCode": "EP111", "value": 1.0, "mark": "N" }, { "paramCode": "EP113", "value": 0.0, "mark": "N" }, { "paramCode": "", "value": 0.0, "mark": "N" }, { "paramCode": "", "value": 0.0, "mark": "N" }, { "paramCode": "", "value": 0.0, "mark": "N" }, { "paramCode": "", "value": 0.0, "mark": "N" }, { "paramCode": "EP112", "value": 1.0, "mark": "N" }, { "paramCode": "EP110", "value": 0.0, "mark": "N" }, { "paramCode": "", "value": 0.0, "mark": "N" }, { "paramCode": "EP120", "value": 21.2, "mark": "N" }, { "paramCode": "EP121", "value": 46.2, "mark": "N" }, { "paramCode": "EP122", "value": 26.5, "mark": "N" }, { "paramCode": "EP123", "value": 41.6, "mark": "N" }, { "paramCode": "EP124", "value": 2.297, "mark": "N" }, { "paramCode": "EP125", "value": 3.6, "mark": "N" }, { "paramCode": "EP126", "value": 4.313, "mark": "N" }, { "paramCode": "EP114", "value": 236.18, "mark": "N" }, { "paramCode": "EP115", "value": 238.15, "mark": "N" }, { "paramCode": "EP116", "value": 236.2, "mark": "N" }, { "paramCode": "EP118", "value": 0.52, "mark": "N" }] }
上面的json字符串格式其实蛮简单的,Stcode表示站点编码,Timestamp表示数据时间,Alarm元素是一个数组,其中paramCode表示报警监测因子编码,value表示报警值,mark表示标记位,N表示正常,B表示异常。
使用rapidjson生成json字符串的两种方式
通常rapidjson生成json有两种方式,如下:
方式1: 使用rapidjson::Document和rapidjson::Document::AllocatorType分配器
使用rapidjson生成上面类似的C++代码如下:
#include <iostream> #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include <iostream> void test2() { rapidjson::Document document; document.SetObject(); rapidjson::Document::AllocatorType& allocator = document.GetAllocator(); rapidjson::Value object1(rapidjson::kObjectType); document.AddMember("StCode", "SS1211054", allocator); document.AddMember("Timestamp", "2020-02-24 13:50:41", allocator); // 数组 rapidjson::Value alarmArray(rapidjson::kArrayType); for (int i = 0 ; i < 10; i++) { char strParamCode[128] = { 0 }; sprintf(strParamCode, "param%d", i + 1); rapidjson::Value objectTemp(rapidjson::kObjectType); rapidjson::Value valueParamCode(strParamCode, document.GetAllocator()); objectTemp.AddMember("paramCode", valueParamCode, allocator); objectTemp.AddMember("value", i + 10, allocator); objectTemp.AddMember("mark", "N", allocator); alarmArray.PushBack(objectTemp, allocator); } document.AddMember("Alarm", alarmArray, allocator); StringBuffer buffer; rapidjson::Writer<StringBuffer> writer(buffer); document.Accept(writer); std::string jsonStr2 = buffer.GetString(); // 打印生成的json字符串 std::cout << "test2(), strJson2为: " << jsonStr2.c_str() << std::endl; } int main(int argc, char* argv[]) { test2(); return 0; }
在VS2017中的程序运行截图如下:

方式2:使用rapidjson::Writer写入json
使用rapidjson生成上面类似的C++代码如下:
#include <iostream> #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include <iostream> void test3() { rapidjson::StringBuffer s; rapidjson::Writer<rapidjson::StringBuffer> writer(s); writer.StartObject(); // Stcode部分 writer.Key("Stcode"); writer.String("SS1211054"); // 构造Timestamp writer.Key("Timestamp"); writer.String("2020-02-27 23:50:41"); writer.Key("Alarm"); writer.StartArray(); // 报警监测数据数组列表 for (int i = 0; i < 5; i++) { char strParamCode[128] = { 0 }; sprintf(strParamCode, "param%d", i); writer.StartObject(); writer.Key("paramCode"); writer.String(strParamCode); writer.Key("value"); writer.Double(i*10 + 3.14); writer.Key("mark"); writer.String("N"); writer.EndObject(); } writer.EndArray(); writer.EndObject(); std::string strJson3 = s.GetString(); // 打印生成的json字符串 std::cout << "test3(), strJson3为: " << strJson3.c_str() << std::endl; } int main(int argc, char* argv[]) { test2(); return 0; }
在VS2017中的程序运行截图如下:

从使用上来说,个人觉得第二种方式:使用rapidjson::Writer写入json更加方便。
参考资料
- rapidjson创建型
- RapidJSON 中文官方文档
- rapidjson常见使用示例
- github地址 A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/
- 使用rapidjson构建生成复杂的json串
- 在线JSON校验格式化工具(Be JSON): https://www.bejson.com