用RapidJSON 的SAX解析器处理influxDB的查询结果

  • RapidJSON是一个C++的JSON解析器及生成器。它的灵感来自RapidXml
  • RapidJSON小而全。它同时支持SAX和DOM风格的API。SAX解析器只有约500行代码
  • RapidJSON快。它的性能可与strlen()相比。可支持SSE2/SSE4.1加速
  • RapidJSON独立。它不依赖于BOOST等外部库。它甚至不依赖于STL
  • RapidJSON对内存友好。在大部分32/64位机器上,每个JSON值只占16或20字节(除字符串外)。它预设使用一个快速的内存分配器,令分析器可以紧凑地分配内存
  • RapidJSON对Unicode友好。它支持UTF-8、UTF-16、UTF-32 (大端序/小端序),并内部支持这些编码的检测、校验及转码。例如,RapidJSON可以在分析一个UTF-8文件至DOM时,把当中的JSON字符串转码至UTF-16。它也支持代理对(surrogate pair)及"\\u0000"(空字符)

官网地址:

http://rapidjson.org/zh-cn/

"SAX" 此术语源于 Simple API for XML

DOM方式较为简单,但是效率较低。SAX适用于已知结构的Json,但是文档较少,例子较少。我研究了一下,在我的应用中用到了,现在把基本实现写出来供大家借鉴。

要实现的是对influxDB查询到的数据的解析,influxDB返回的结果是Json,且为固定格式,用SAX格式,最好不过了。先前用的是DOM方式,但是效率有点低。

{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "WEMW",
                    "columns": [
                        "time",
                        "sample",
                        "iGenPower",
                        "trubId"
                    ],
                    "values": [
                        [
                            "2018-08-31T00:18:23Z",
                            "2.48",
                            "0",
                            null
                        ],
                        [
                            "2018-08-31T08:25:18Z",
                            "3.08",
                            "40",
                            null
                        ],
                        [
                            "2018-08-31T22:15:32Z",
                            "2.37",
                            "0",
                            null
                        ],
                        [
                            "2018-09-01T08:09:17Z",
                            "2.23",
                            "0",
                            null
                        ],
                        [
                            "2018-09-01T15:22:43Z",
                            "2.67",
                            "52",
                            null
                        ],
                        [
                            "2018-09-01T21:34:03Z",
                            "2.72",
                            "0",
                            null
                        ]
                    ]
                }
            ]
        }
    ]
}

上代码 。

读取columns这一行的数据。

struct columnReader {
	bool inColArray = false;
	std::vector<std::string> columns;

	bool Key(const char *str, SizeType length, bool copy) {
		if (strncmp(str, "columns", length) == 0) inColArray = true;
		return true;
	}
	bool String(const char *str, SizeType length, bool copy) {
		if (inColArray) columns.emplace_back(str);
		return true;
	}
	bool EndArray(SizeType elementCount) { return !inColArray; /*stop after column array*/ }
	bool Null() { return true; }
	bool Bool(bool b) { return true; }
	bool Int(int i) { return true; }
	bool Uint(unsigned u) { return true; }
	bool Int64(int64_t i) { return true; }
	bool Uint64(uint64_t u) { return true; }
	bool Double(double d) { return true; }
	bool RawNumber(const char *str, SizeType length, bool copy) { return true; }
	bool StartObject() { return true; }
	bool EndObject(SizeType memberCount) { return true; }
	bool StartArray() { return true; }
};

读取具体的values

struct valuesReader {
	bool isInValueArray = false;
	int numRow = 0;
	int numColumn = 0;
	int inValueArray = 0;//1进入values,2进入某一行


	vector<vector<string>  > valueList;
	vector<string>	value;

	int row = 0;
	bool Key(const char *str, SizeType length, bool copy) {
		//if (strncmp(str, "series", length) == 0) inSeriesArray = true;
		if (strncmp(str, "values", length) == 0) {
			isInValueArray = true;
			inValueArray++;
		}
		return true;
	}
	bool StartArray() {
		if (isInValueArray){
			if (inValueArray == 0)
			{
				inValueArray++;
				numRow++;
			}
			else if (inValueArray == 1)
			{
				inValueArray++;
				numRow++;
			}

		}
		return true;
	}


	bool String(const char *str, SizeType length, bool copy) {
		if (inValueArray == 2) value.emplace_back(str);
		return true;
	}
	bool Null() {
		if (inValueArray == 2) value.push_back("");
		return true;
	}
	bool EndArray(SizeType elementCount) {
		if (inValueArray == 2) {
			--inValueArray;
			numColumn = 0;
			valueList.emplace_back(std::move(value));
		}
		else if (inValueArray == 1) {
			--inValueArray;
		}
		return true;
	}


	bool Bool(bool b) { return true; }
	bool Int(int i) { return true; }
	bool Uint(unsigned u) { return true; }
	bool Int64(int64_t i) { return true; }
	bool Uint64(uint64_t u) { return true; }
	bool Double(double d) { return true; }
	bool RawNumber(const char *str, SizeType length, bool copy) { 
		if (inValueArray == 2) value.emplace_back(std::string{ str, length }); 
		return true;
	}
	bool StartObject() { return true; }
	bool EndObject(SizeType memberCount) { return true; }

};

 

最后是调用2种Handler进行测试:

void f1()
{
	Reader reader;
	StringStream ss(json);

	ifstream fin("result1000.json");
	//创建字符串流对象
	stringstream sin;
	//把文件流中的字符输入到字符串流中
	sin << fin.rdbuf();
	//获取字符串流中的字符串
	string str = sin.str();
	fin.close();
	fin.clear();
	rapidjson::StringStream ss1(str.c_str());

	columnReader columnHandler;
	//reader.Parse(ss1, handler);
	//reader.Parse(ss1, columnHandler);
	valuesReader valuesHandler;

	reader.Parse<kParseNumbersAsStringsFlag>(ss1, valuesHandler);

}
void main() {
	
	char c;
	do{
		for (int i = 0; i < 10;i++)
			f1();
		c = getchar();
	} while (c);

}

kParseNumbersAsStringsFlag是这样用的:

reader.Parse<kParseNumbersAsStringsFlag>(ss1, valuesHandler);

经测试,比DOM方式快了许多。

 

代码参考了https://github.com/f4bsch/influxdb-hp的实现,在此注明。

高效的 C++ JSON 解析/生成器,提供 SAX 及 DOM 风格 API 简介 RapidJSON 是一个 C++ 的 JSON 解析器及生成器。它的灵感来自 RapidXml。 RapidJSON 小而全。它同时支持 SAX 和 DOM 风格的 APISAX 解析器只有约 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)是一个轻量的xx交换格式。RapidJSON 应该完全遵从 RFC7159/ECMA-404,并支持可选的放宽语法。 一、使用说明 rapidjson.fne 为英文原版 rapidjson_cn.fne  为中文翻译版(翻译的中文命令有点糙),使用中文版时,请改文件名为rapidjson.fne 不然会出错的。 rapidjson_static.lib 为静态库,部分中文英文。 中文和英文可以无缝切换,直接替换支持库文件就可以了。 本支持库由VS2017,所以编译时,也必须要用VS2017编译。 VC2017连接器下载地址: http://bbs.eyuyan.com/read.php?tid=410252  VS2017易支持库模板+VC2017链接器(讨厌vc6的可看)-->hxznhf http://bbs.eyuyan.com/read.php?tid=408541  全易论坛独创首发,Vs2017Linker编译器 -->cs666 关于RapidJSON的相关问题,请看: http://rapidjson.org/zh-cn/md_doc_faq_8zh-cn.html 使用有声明问题请加QQ群: 心宇->EVAxx研究中心(255829517) 现在支持库完善了大概80%左右,已经可以正常使用,剩下20%是关于 reader 和编码以及一些参数有关,暂时对易不是很重要,后面也会完善。 二、版权声明 本支持库为封装TX开源项目 RapidJSON ,为解决易语言没有高性能JSON库的问题。 项目官网:http://rapidjson.org/zh-cn/ github:https://github.com/Tencent/rapidjson/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

路边闲人2

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

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

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

打赏作者

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

抵扣说明:

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

余额充值