Rapidjson is a fast JSON parser/generator for C++ with both SAX/DOM style API.
其所有源代码都包含在源码包的include/rapidjson/include目录下,使用时只需要include相应的头文件即可。
详细的介绍见rapid官方文档
先看下rapidjson中的value有哪些类型, rapidjson中定义的类型的先后顺序为:
“Null”, “False”, “True”, “Object”, “Array”, “String”, “Number”
其中Number类型包含int, uint, int64, uint64, double
Type GetType() const { return static_cast(data_.f.flags & kTypeMask); }
bool IsNull() const { return data_.f.flags == kNullFlag; }
bool IsFalse() const { return data_.f.flags == kFalseFlag; }
bool IsTrue() const { return data_.f.flags == kTrueFlag; }
bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
bool IsObject() const { return data_.f.flags == kObjectFlag; }
bool IsArray() const { return data_.f.flags == kArrayFlag; }
bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
有了这个后,我们就可以根据dom节点的类型来解析出对应的value,伪代码如下如下:
#define ERROR -1
#define OK 0
string jsonstr = {"key":value, ...};
Document document;
if(document.Parse(jsonstr.c_str()).HasParseError())
{
return ERROR;
}
const rapidjson::Value& value = document["key"]; //use [] operator to get node value
/** use FindMember function
auto var = document.FindMember("key");
if(var != document.MemberEnd())
{
rapidjson::Value& value = var->value;
}
*/
if(value.IsNull())
{
...
}
else if(value.IsObject())
{
//continue to parse
...
}else if(value.isString())
{
cout << value.GetString();
}else if(value.isNumber())
{
if(value.isInt())
{...
}else if(value.isUint())
{...
}else ...
}
...
另外,我们也可以实现一个打印json串内容的函数:
int printJsonString(string& jsonstr)
{
Document document;
if(document.Parse(json).HasParseError())
{
return -1;
}
static const char* kTypeNames[] =
{ "Null", "False", "True", "Object", "Array", "String", "Number" };
for (auto& m : document.GetObject())
{
printf("Type of member %s is %s\n",
m.name.GetString(), kTypeNames[m.value.GetType()]);
if(m.value.isNull())
{
printf("key = %s, value = %s\n", m.name.GetString(), "null");
}else if(m.value.isString())
{
printf("key = %s, value = %s\n", m.name.GetString(), m.value.GetString());
}else if(...)
...
}
return 0;
}
上述解析的json串是通过string or char字符串输入的,如果json串来源于文件的话,就需要使用如下的方法调用Parse方法(详细使用说明参考rapidjson文件流):
#include "rapidjson/filereadstream.h"
#include
using namespace rapidjson;
FILE* fp = fopen("big.json", "rb"); // 非 Windows 平台使用 "r"
char readBuffer[65536];
FileReadStream is(fp, readBuffer, sizeof(readBuffer));
Document d;
d.ParseStream(is);
fclose(fp);
有几种方法可用于构造json串:
int constructJsonStr1(string& outputStr)
{
rapidjson::StringBuffer json_str_buf;
rapidjson::Writer json_writer(json_str_buf);
json_writer.StartObject();
json_writer.String("id");
json_writer.Uint(0);
json_writer.String("name");
json_writer.String("zhangsan");
json_writer.String("data");
json_writer.StartObject();
json_writer.String("age");
json_writer.Uint(20);
json_writer.String("province");
json_writer.String("guangdong");
json_writer.EndObject();
json_writer.EndObject();
outputStr = json_str_buf.GetString();
cout << outputStr << endl;
return 0;
}
int constructJsonStr2()
{
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType & allocator = document.GetAllocator();
document.AddMember("id", 0, allocator);
document.AddMember("name", rapidjson::StringRef("zhangsan"), allocator);
rapidjson::Value data_obj(rapidjson::kObjectType);
data_obj.AddMember("age", 20, allocator);
data_obj.AddMember("province", rapidjson::StringRef("guangdong"), allocator);
document.AddMember("data", data_obj, allocator);
rapidjson::StringBuffer buffer;
rapidjson::Writer writer(buffer);
document.Accept(writer);
cout << buffer.GetString() << endl;
return 0;
}
Document d;
// 使用 Set() 创建 DOM
Pointer("/project").Set(d, "RapidJSON");
Pointer("/stars").Set(d, 10);
// { "project" : "RapidJSON", "stars" : 10 }
p.s.:
Document document;
Value author;
char buffer[10];
int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // 动态创建的字符串。
author.SetString(buffer, len, document.GetAllocator());
memset(buffer, 0, sizeof(buffer));
// 清空 buffer 后 author.GetString() 仍然包含 "Milo Yip"
对于字符串字面量或有安全生命周期的字符串,可以使用 const-string 版本的 SetString(),它没有 allocator 参数。对于字符串字面量(或字符数组常量),只需简单地传递字面量,又安全又高效:
Value s;
s.SetString("rapidjson"); // 可包含空字符,长度在编译萁推导
s = "rapidjson";
对于字符指针,RapidJSON 需要作一个标记,代表它不复制也是安全的。可以使用 StringRef 函数