- 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"(空字符)
官网地址:
"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的实现,在此注明。