RapidJSON 是一个 C++ 的 JSON 解析器及生成器。它的灵感来自 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"(空字符)
使用方法:RapidJSON: 首页http://rapidjson.org/zh-cn/index.html
首先加载头文件#include"rapidjson/reader.h" #include"rapidjson/schema.h" #include"rapidjson/stream.h" #include"rapidjson/stringbuffer.h" #include"rapidjson/uri.h" #include"rapidjson/writer.h" using namespace rapidjson;
这里 rapidjson 为作用域;
#include "rapidjson/document.h" using namespace rapidjson; Document document; 创建DOM树 document.Parse(json); 加载解析的json文件
那么现在该 JSON 就会被解析至 document 中,成为一棵 *DOM 树 *:
解析过程(也就是读取过程):
定义 dom 树 Document dom;//定义DOM树根 dom.Parse(str); //将解析的文本加载DOM树上 这里str必须为const char* assert(dom.IsObject()); //断言数据类型 为树对象
举例:
{
"hello": "world",
"t": true ,
"f": false,
"n": null,
"i": 123,
"pi": 3.1416,
"a": [1, 2, 3, 4]
}
让我们查询一下根 Object 中有没有 "hello" 成员。由于一个 Value 可包含不同类型的值,我们可能需要验证它的类型,并使用合适的 API 去获取其值。在此例中,"hello" 成员关联到一个 JSON String。
assert(document.HasMember("hello"));
assert(document["hello"].IsString());
printf("hello = %sn", document["hello"].GetString());
结果:world
JSON True/False 值是以 bool 表示的。
assert(document["t"].IsBool());
printf("t = %sn", document["t"].GetBool() ? "true" : "false");
结果:true
JSON Null 值可用 IsNull() 查询。
printf("n = %sn", document["n"].IsNull() ? "null" : "?");
结果:null
JSON Number 类型表示所有数值。然而,C++ 需要使用更专门的类型。
assert(document["i"].IsNumber());
// 在此情况下,IsUint()/IsInt64()/IsUint64() 也会返回 true
assert(document["i"].IsInt());
printf("i = %dn", document["i"].GetInt());
// 另一种用法: (int)document["i"]
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
printf("pi = %gn", document["pi"].GetDouble());
结果:i = 123
结果:pi = 3.1416
JSON Array 包含一些元素。
// 使用引用来连续访问,方便之余还更高效。
const Value& a = document["a"];
assert(a.IsArray());
for (SizeType i = 0; i < a.Size(); i++) // 使用 SizeType 而不是 size_t
printf("a[%d] = %dn", i, a[i].GetInt());
结果:
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
反解析过程(也就是写过程):char name[] = "LI HUA"; string gender = "boy"; vectorhobby = { "足球","篮球","电影" }; map score = { {"math",100},{"Chinese",86},{"English",85} }; string Lover_name = "Xiao Hong"; string Love_gender = "girl"; vector Lover_hobby = { "画画","跳舞","唱歌" }; map Lover_score = { {"数学", 78.5},{"语文", 89},{"英语", 90} };
开始写:
StringBuffer s; 定义缓冲buff 写入文件 Writerwriter(s);
writer.StartObject();
writer.Key("name");
writer.String(name);
writer.Key("gender");
writer.String(gender.c_str());
writer.Key("hobby");
writer.StartArray();
for (const auto& item : hobby)
{
writer.String(item.c_str());
}
writer.EndArray();
writer.Key("score");
writer.StartObject();
for (auto &item : Lover_score) {
writer.Key((item.first).c_str());
writer.Double(item.second);
}
writer.EndObject();
writer.Key("lover");
writer.StartObject();
writer.Key("name");
writer.String(Lover_name.c_str());
writer.Key("gender");
writer.String(Love_gender.c_str());
writer.Key("hobby");
writer.StartArray();
for (auto &item : Lover_hobby) {
writer.String((item.c_str()));
}
writer.EndArray();
writer.Key("score");
writer.StartObject();
for (auto &item : Lover_score) {
writer.Key((item.first).c_str());
writer.Double(item.second);
}
writer.EndObject();
writer.EndObject();
writer.EndObject();//全局对象
std::string outFileName = R"(C:UsersdellDesktopdocument.json)";
std::ofstream outfile(outFileName, std::ios::trunc);
outfile << "n";
outfile << s.GetString();
outfile.close();
结果展示:



