专栏首页ccf19881030的博客使用rapidJson C++库生成JSON字符串

使用rapidJson C++库生成JSON字符串

前言

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更加方便。

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • VS2005中关于char[]转换成LPCWSTR的问题

          最近在使用VS2005,有时VC6.0中的工程拿到VC2005下经常会出现问题,比如最令我头痛的问题之一是:

    ccf19881030
  • Windows7下命令行使用MySQL

    1、在Win7环境下安装MySQL,关于安装方法可以参考文章: Win7系统安装MySQL5.5.21图解教程、win7安装MySql

    ccf19881030
  • 进程与线程的区别

    一、操作系统中线程和进程的概念 现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。 进程是指一个内存中运行的应用程序,每个进程都有自己独立的...

    ccf19881030
  • rapidJson 的使用

    bear_fish
  • swagger2自定义隐藏实体类属性

    但是通过阅读源码找到了展开参数的类springfox.documentation.spring.web.readers.parameter.ModelAttri...

    吟风者
  • 定制开发专属分销系统,低成本获取用户流量!

    无论你是否熟悉分销这种推广模式,以下场景已经越来越多的出现在你的朋友圈,微信群,以及生活当中。

    用户2356481
  • 简易关键点标注软件分享

    代码地址:https://github.com/pprp/landmark_annotation

    BBuf
  • P05_kafka_2.9.2-0.8.1集群搭建

    安装scala 2.11.4 1、将课程提供的scala-2.11.4.tgz使用WinSCP拷贝到sparkproject1的/usr/local目录下。 ...

    Albert陈凯
  • 软件工程攻略

    由于软件的开发存在这么多的问题, 其主要原因是规模太大并且缺少一种有效的方法来进行整个软件的开发 从而引出软件工程

    Mezereon
  • Leetcode 【495、835】

    抛开移动的过程只看移动完成的结果。记图片左上角为顶点 (0, 0),正方形边长为 N,要使得两张图片有重叠,那么其中一张图片移到的某一点 (x, y) 一定与另...

    echobingo

扫码关注云+社区

领取腾讯云代金券