rapidjson相比jsoncpp性能高出太多,使用接口一樣的簡單的。官方中文幫助文檔:http://rapidjson.org/zh-cn/。
rapidjson的Move語意,請瀏覽http://rapidjson.org/zh-cn/md_doc_tutorial_8zh-cn.html#MoveSemantics,
示例:
rapidjson::Value a(123);
rapidjson::Value b(456);
b = a; // a變成Null,b變成數字123,這樣的做法是基於性能考慮
除了上述示例的復制語句外,AddMember()和PushBack()也采用了Move語意。
深復制Value:
Value v1("foo");
// Value v2(v1); // 不容許
Value v2(v1, a); // 制造一個克隆,v1不變
Document d;
v2.CopyFrom(d, a); // 把整個document復制至v2,d不變
rapidjson為了最大化性能,大量使用了淺拷貝,使用之前一定要了解清楚。
如果采用了淺拷貝,特別要注意局部對象的使用,以防止對象已被析構了,卻還在被使用。
// 需要#include的頭文件:
#include <rapidjson/document.h>
#include <rapidjson/error/en.h> // en為english的簡寫,定義了取出錯信息的函數GetParseError_En(errcode)
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
// 示例1:解析一個字符串
// 運行輸出結果:
// count=2
// name=zhangsan
// name=wangwu
void x1()
{
rapidjson::Document document; // 定義一個Document對象
std::string str = "{\"count\":2,\"names\":[\"zhangsan\",\"wangwu\"]}";
document.Parse(str.c_str()); // 解析,Parse()無返回值,也不會拋異常
if (document.HasParseError()) // 通過HasParseError()來判斷解析是否成功
{
// 可通過GetParseError()取得出錯代碼,
// 注意GetParseError()返回的是一個rapidjson::ParseErrorCode類型的枚舉值
// 使用函數rapidjson::GetParseError_En()得到錯誤碼的字符串說明,這里的En為English簡寫
// 函數GetErrorOffset()返回出錯發生的位置
printf("parse error: (%d:%d)%s\n", document.GetParseError(), document.GetErrorOffset(), rapidjson::GetParseError_En(document.GetParseError()));
}
else
{
// 判斷某成員是否存在
if (!document.HasMember("count") || !document.HasMember("names"))
{
printf("invalid format: %s\n", str.c_str());
}
else
{
// 如果count不存在,則運行程序會掛,DEBUG模式下直接abort
rapidjson::Value& count_json = document["count"];
// 如果count不是整數類型,調用也會掛,DEBUG模式下直接abort
// GetInt()返回類型為int
// GetUint()返回類型為unsigned int
// GetInt64()返回類型為int64_t
// GetUint64()返回類型為uint64_t
// GetDouble()返回類型為double
// GetString()返回類型為char*
// GetBool()返回類型為bool
int count = count_json.GetInt();
printf("count=%d\n", count);
// 方法GetType()返回枚舉值: kNullType,kFalseType,kTrueType,kObjectType,kArrayType,kStringType,kNumberType
// 可用IsArray()判斷是否為數組,示例: { "a": [1, 2, 3, 4] }
// 用IsString()判斷是否為字符串值
// 用IsDouble()判斷是否為double類型的值,示例: { "pi": 3.1416 }
// 用IsInt()判斷是否為int類型的值
// 用IsUint()判斷是否為unsigned int類型的值
// 用IsInt64()判斷是否為int64_t類型的值
// 用IsUint64()判斷是否為uint64_t類型的值
// 用IsBool()判斷是否為bool類型的值
// 用IsFalse()判斷值是否為false,示例: { "t": true, "f": false }
// 用IsTrue()判斷值是否為true
// 用IsNull()判斷值是否為NULL,示例: { "n": null }
// 更多說明可瀏覽:
// https://miloyip.gitbooks.io/rapidjson/content/zh-cn/doc/tutorial.zh-cn.html
const rapidjson::Value& names_json = document["names"];
for (rapidjson::SizeType i=0; i<names_json.Size(); ++i)
{
std::string name = names_json[i].GetString();
printf("name=%s\n", name.c_str());
}
}
}
}
// 示例2:構造一個json並轉成字符串
// 輸出結果:
// {"count":2,"names":[{"name":"zhangsan"},{"name":"wangwu"}]}
void x2()
{
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
writer.StartObject();
// count
writer.Key("count");
writer.Int(2);
// 寫4字節有符號整數: Int(int32_t x)
// 寫4字節無符號整數: Uint(uint32_t x)
// 寫8字節有符號整數: Int64(int64_t x)
// 寫8字節無符號整數: Uint64(uint64_t x)
// 寫double值: Double(double x)
// 寫bool值: Bool(bool x)
// names
writer.Key("names");
writer.StartArray();
writer.StartObject();
writer.Key("name");
writer.String("zhangsan");
writer.EndObject();
writer.StartObject();
writer.Key("name");
writer.String("wangwu");
writer.EndObject();
writer.EndArray();
writer.EndObject();
// 以字符串形式打印輸出
printf("%s\n", buffer.GetString());
}
// 示例3:修改一個已有的json字符串
// 運行輸出結果:
// {"name":"wangwu","age":22}
void x3()
{
rapidjson::Document document;
std::string str = "{\"name\":\"zhangsan\",\"age\":20}";
document.Parse(str.c_str());
rapidjson::Value& name_json = document["name"];
rapidjson::Value& age_json = document["age"];
std::string new_name = "wangwu";
int new_age = 22;
// 注意第三個參數是document.GetAllocator(),相當於深拷貝,rapidjson會分配一塊內存,然后復制new_name.c_str(),
// 如果不指定第三個參數,則是淺拷貝,也就是rapidjson不會分配一塊內存,而是直接指向new_name.c_str(),省去復制提升了性能
// 官方說明:
// http://rapidjson.org/zh-cn/md_doc_tutorial_8zh-cn.html#CreateString
name_json.SetString(new_name.c_str(), new_name.size(), document.GetAllocator());
age_json.SetInt(new_age);
// 轉成字符串輸出
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
printf("%s\n", buffer.GetString());
}
// 示例4:讀數組
// 運行輸出結果:
// zhangsan wangwu
void x4()
{
rapidjson::Document document;
std::string str = "{\"count\":2,\"names\":[{\"name\":\"zhangsan\"},{\"name\":\"wangwu\"}]}";
document.Parse(str.c_str());
if (document.HasParseError())
{
printf("parse error: %d\n", document.GetParseError());
}
else
{
rapidjson::Value& names_json = document["names"];
for (rapidjson::SizeType i=0; i<names_json.Size(); ++i)
{
if (names_json[i].HasMember("name"))
{
rapidjson::Value& name_json = names_json[i]["name"];
printf("%s ", name_json.GetString());
}
}
printf("\n");
}
}
// 示例5: 以Writer構造一個json,然后修改它,最后轉成字符串
// 運行輸出結果:
// {"count":2}
// {"count":8}
void x5()
{
rapidjson::StringBuffer buffer1;
rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
writer1.StartObject();
writer1.Key("count");
writer1.Int(2);
writer1.EndObject();
printf("%s\n", buffer1.GetString());
// 轉成Document對象
rapidjson::Document document;
document.Parse(buffer1.GetString());
// 修改
rapidjson::Value& count_json = document["count"];
count_json.SetInt(8);
// 轉成字符串
rapidjson::StringBuffer buffer2;
rapidjson::Writer<rapidjson::StringBuffer> writer2(buffer2);
document.Accept(writer2);
printf("%s\n", buffer2.GetString());
}
// 示例6: 以Document構造一個json,然后修改它,最后轉成字符串
// 運行輸出結果:
// {"count":3,"names":[{"id":1,"name":"zhangsan"}]}
// {"count":9,"names":[{"id":1,"name":"zhangsan"}]}
void x6()
{
rapidjson::Document document;
std::string str = "{}"; // 這個是必須的,且不能為"",否則Parse出錯
document.Parse(str.c_str());
// 新增成員count
document.AddMember("count", 3, document.GetAllocator());
// 新增數組成員
rapidjson::Value array(rapidjson::kArrayType);
rapidjson::Value object(rapidjson::kObjectType); // 數組成員
object.AddMember("id", 1, document.GetAllocator());
object.AddMember("name", "zhangsan", document.GetAllocator());
// 如果數組添加無名字的成員,定義Value時應當改成相應的類型,如:
//rapidjson::Value value(rapidjson::kStringType);
//rapidjson::Value value(rapidjson::kNumberType);
//rapidjson::Value value(rapidjson::kFalseType);
//rapidjson::Value value(rapidjson::kTrueType);
//array.PushBack(value, document.GetAllocator());
//效果將是這樣:'array':[1,2,3,4,5]
// 注意下面用法編譯不過:
//std::string str1 = "hello";
//object.AddMember("name", str1.c_str(), document.GetAllocator());
//const char* str2 = "hello";
//object.AddMember("name", str2, document.GetAllocator());
//
// 下面這樣可以:
//object.AddMember("name", "hello", document.GetAllocator());
//const char str3[] = "hello";
//object.AddMember("name", str3, document.GetAllocator());
//
//std::string str4 = "#####";
//rapidjson::Value v(str4.c_str(), document.GetAllocator());
//obj.AddMember("x", v, document.GetAllocator());
// 上面兩行也可以寫在一行:
//obj.AddMember("x", rapidjson::Value(str4.c_str(), document.GetAllocator()).Move(), document.GetAllocator());
// 添加到數組中
array.PushBack(object, document.GetAllocator());
// 添加到document中
document.AddMember("names", array, document.GetAllocator());
// 轉成字符串輸出
rapidjson::StringBuffer buffer1;
rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
document.Accept(writer1);
printf("%s\n", buffer1.GetString());
// 修改值
rapidjson::Value& count_json = document["count"];
count_json.SetInt(9);
// 再次輸出
rapidjson::StringBuffer buffer2;
rapidjson::Writer<rapidjson::StringBuffer> writer2(buffer2);
document.Accept(writer2);
printf("%s\n", buffer2.GetString());
}
// 不轉義就輸出
// 示例7: 以Document構造一個json,然后修改它,最后轉成字符串
// 運行輸出結果:
// x7=>
// {"title":"\u8D2B\u56F0\u5B64\u513F\u52A9\u517B"}
void x7()
{
std::string root = "{}";
rapidjson::Document document;
document.Parse(root.c_str());
std::string title = "\u8D2B\u56F0\u5B64\u513F\u52A9\u517B";
document.AddMember("title", rapidjson::Value(title.c_str(), document.GetAllocator()).Move(), document.GetAllocator());
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<> > writer(buffer);
// 如果上面一句改成普通的:
// rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
// 則輸出將變成:
// x7=>
// 貧困孤兒助養
document.Accept(writer);
printf("x7=>\n%s\n", buffer.GetString());
}
// 示例8:構造空對象和數組
// 運行輸出結果:
// {"age":{},"times":{},"names":[],"urls":[],"books":[]}
// {"age":6,"times":{},"names":[],"urls":[],"books":[]}
void x8()
{
rapidjson::Document document;
document.Parse("{}"); // 這里換成document.SetObject()也可以
// 下面為2種構造空對象的方法
document.AddMember("age", rapidjson::Value(rapidjson::kObjectType).Move(), document.GetAllocator());
document.AddMember("times", rapidjson::Value().SetObject(), document.GetAllocator());
// 下面為2種構造空數組的方法
document.AddMember("names", rapidjson::Value(rapidjson::kArrayType).Move(), document.GetAllocator());
document.AddMember("urls", rapidjson::Value(rapidjson::kArrayType).Move(), document.GetAllocator());
document.AddMember("books", rapidjson::Value().SetArray(), document.GetAllocator());
rapidjson::StringBuffer buffer1;
rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
document.Accept(writer1);
printf("%s\n", buffer1.GetString());
rapidjson::Value& age = document["age"];
age.SetInt(6);
rapidjson::StringBuffer buffer2;
rapidjson::Writer<rapidjson::StringBuffer> writer2(buffer2);
document.Accept(writer2);
printf("%s\n", buffer2.GetString());
}
// 刪除數組元素
// 示例運行輸出:
// { "names": [ {"name":"zhangsan","age":100}, {"name":"wangwu","age":90}, {"name":"xiaozhang","age":20} ]}
// {"names":[{"name":"zhangsan","age":100},{"name":"wangwu","age":90}]}
void x9()
{
std::string str = "{ \"names\": [ {\"name\":\"zhangsan\",\"age\":100}, {\"name\":\"wangwu\",\"age\":90}, {\"name\":\"xiaozhang\",\"age\":20} ]}";
rapidjson::Document document;
document.Parse(str.c_str());
rapidjson::Value& names_json = document["names"];
for (rapidjson::Value::ValueIterator iter=names_json.Begin(); iter!=names_json.End();)
{
std::string name = (*iter)["name"].GetString();
// 不要小張了
if (name == "xiaozhang")
iter = names_json.Erase(iter);
else
++iter;
}
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
printf("%s\n", str.c_str());
printf("%s\n", buffer.GetString());
}
int main()
{
x1();
x2();
x3();
x4();
x5();
x6();
x7();
x8();
x9();
return 0;
}
// 示例:不轉義中文
// 運行輸出結果:
//{"title":"貧困孤兒助養"}
//{"title":"\u8D2B\u56F0\u5B64\u513F\u52A9\u517B"}
//g++ -g -o b b.cpp -I/usr/local/thirdparty/rapidjson/include
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <string>
#include <stdio.h>
int main()
{
std::string str = "{\"title\":\"\u8d2b\u56f0\u5b64\u513f\u52a9\u517b\"}";
rapidjson::Document document;
document.Parse(str.c_str());
if (document.HasParseError())
{
printf("parse %s failed\n", str.c_str());
exit(1);
}
rapidjson::StringBuffer buffer1;
rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
document.Accept(writer1);
printf("%s\n", buffer1.GetString());
rapidjson::StringBuffer buffer2;
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<> > writer2(buffer2);
document.Accept(writer2);
printf("%s\n", buffer2.GetString());
return 0;
}
// 輔助函數:任意類型都以字符串返回,
// 如果不存在,或者為數組則返回空字符串。
std::string rapidjson_string_value(rapidjson::Value& value, const std::string& name)
{
if (!value.HasMember(name.c_str()))
return std::string("");
const rapidjson::Value& child = value[name.c_str()];
if (child.IsString())
return child.GetString();
char str[100];
if (child.IsInt())
{
snprintf(str, sizeof(str), "%d", child.GetInt());
}
else if (child.IsInt64())
{
// 為使用PRId64,需要#include <inttypes.h>,
// 同時編譯時需要定義宏__STDC_FORMAT_MACROS
snprintf(str, sizeof(str), "%"PRId64, child.GetInt64());
}
else if (child.IsUint())
{
snprintf(str, sizeof(str), "%u", child.GetUint());
}
else if (child.IsUint64())
{
snprintf(str, sizeof(str), "%"PRIu64, child.GetUint64());
}
else if (child.IsDouble())
{
snprintf(str, sizeof(str), "%.2lf", child.GetDouble());
}
else if (child.IsBool())
{
if (child.IsTrue())
strcpy(str, "true");
else
strcpy(str, "false");
}
else
{
str[0] = '\0';
}
return str;
}
// 輔助函數:
// 當為int32_t值,或字符串實際為int32_t值時,返回對應的int32_t值,其它情況返回0
int32_t rapidjson_int32_value(rapidjson::Value& value, const std::string& name)
{
if (!value.HasMember(name.c_str()))
return 0;
const rapidjson::Value& child = value[name.c_str()];
if (child.IsInt())
{
return child.GetInt();
}
else if (child.IsString())
{
return atoi(child.GetString());
}
return 0;
}
// 輔助函數:
// 當為int64_t值,或字符串實際為int64_t值時,返回對應的int64_t值,其它情況返回0
int64_t rapidjson_int64_value(rapidjson::Value& value, const std::string& name)
{
if (!value.HasMember(name.c_str()))
return 0;
const rapidjson::Value& child = value[name.c_str()];
if (child.IsInt64())
{
return child.GetInt64();
}
else if (child.IsString())
{
return (int64_t)atoll(child.GetString());
}
return 0;
}
// 輔助函數:
// 當為uin32_t值,或字符串實際為uin32_t值時,返回對應的uin32_t值,其它情況返回0
uint32_t rapidjson_uint32_value(rapidjson::Value& value, const std::string& name)
{
if (!value.HasMember(name.c_str()))
return 0;
const rapidjson::Value& child = value[name.c_str()];
if (child.IsUint())
{
return child.GetUint();
}
else if (child.IsString())
{
return (uint32_t)atoll(child.GetString());
}
return 0;
}
// 輔助函數:
// 當為uin64_t值,或字符串實際為uin64_t值時,返回對應的uin64_t值,其它情況返回0
uint64_t rapidjson_uint64_value(rapidjson::Value& value, const std::string& name)
{
if (!value.HasMember(name.c_str()))
return 0;
const rapidjson::Value& child = value[name.c_str()];
if (child.IsUint64())
{
return child.GetUint64();
}
else if (child.IsString())
{
return (uint64_t)atoll(child.GetString());
}
return 0;
}
// schema使用示例:
json的schema用來檢驗json數據,它也采用了json格式。
rapidjson::Document schema_document;
schema_document.Parse(schema.c_str());
if (!schema_document.HasParseError())
{
rapidjson::Document document;
document.Parse(str.c_str());
if (!document.HasParseError())
{
SchemaDocument schema(schema_document);
SchemaValidator validator(schema);
if (!document.Accept(validator))
{
// 檢驗出錯,輸出錯誤信息
StringBuffer sb;
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
printf("Invalid schema: %s\n", sb.GetString());
printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
printf("Invalid document: %s\n", sb.GetString());
}
}
}
示例json:
{
"id": 1,
"name": "A green door",
"price": 12.50,
"tags": ["home", "green"]
}
上段json對應的schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "integer"
},
"name": {
"description": "Name of the product",
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": ["id", "name", "price"]
}
"title"和"description"是描述性的,可以不寫。$schema也是可選的,依據的是《JSON Schema Draft v4》。
X1)rapidjson的“坑”
使用不當,則會掉進“坑”里。下列代碼在valgrind中運行時,會報大量錯誤,而且如果sub是在一個循環中被AddMember,則無法得到預期的結果。
從現象看像是sub析構后仍在被使用,為驗證這個推測,改成:rapidjson::Document* sub = new rapidjson::Document;,然后再使用不但valgrind不報錯,而且循環使用也沒問題,那么可以肯定AddMember是淺拷貝,這樣一來使用就不方便了,除非還有深拷貝的調用方式。
#include <rapidjson/schema.h>
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <string>
#include <vector>
int main()
{
rapidjson::Document doc;
doc.Parse("{}");
{ // 目的是讓sub在printf時已無效
rapidjson::Document sub;
sub.Parse("{\"name\":\"tom\"}");
doc.AddMember("sub", sub, doc.GetAllocator());
}
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
printf("%s\n", buffer.GetString());
return 0;
}
上述代碼在valgrind中跑,會報錯大量如下這樣的錯誤:
==30425== Invalid read of size 2
==30425== at 0x804B008: rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::IsString() const (document.h:947)
==30425== by 0x8051632: bool rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::Accept<rapidjson::Writer<rapidjson::GenericStringBuffer<rapidjson::UTF8<char>, rapidjson::CrtAllocator>, rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator, 0u> >(rapidjson::Writer<rapidjson::GenericStringBuffer<rapidjson::UTF8<char>, rapidjson::CrtAllocator>, rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator, 0u>&) const (document.h:1769)
==30425== by 0x80488CE: main (f.cpp:30)
==30425== Address 0x428eb62 is 58 bytes inside a block of size 65,548 free'd
==30425== at 0x4023329: free (vg_replace_malloc.c:473)
==30425== by 0x804BC72: rapidjson::CrtAllocator::Free(void*) (allocators.h:79)
==30425== by 0x804BDD7: rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>::Clear() (allocators.h:148)
==30425== by 0x804BE2E: rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>::~MemoryPoolAllocator() (allocators.h:140)
==30425== by 0x804BE5F: rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::Destroy() (document.h:2382)
==30425== by 0x804BE7E: rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::~GenericDocument() (document.h:2064)
正確可以使用的寫法:
#include <rapidjson/schema.h>
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <string>
#include <vector>
int main()
{
std::vector<rapidjson::Document*> subs;
rapidjson::Document doc;
doc.Parse("{}");
{
// 注意,下面沒有使用Document的默認構造,
// 而是指定Allocator為其父的Allocator。
// 如果存在多級Document,一定要統一使用根Document的Allocator,
// 原因是Allocator分配的內存會隨Document析構被釋放掉!
//
// 如果不這樣做,必須保證sub的生命在doc之后才結束。
rapidjson::Document sub(&doc.GetAllocator());
sub.Parse("{\"name\":\"tom\"}");
doc.AddMember("sub", sub, doc.GetAllocator());
}
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
printf("%s\n", buffer.GetString());
for (std::vector<rapidjson::Document*>::size_type i=0; i<subs.size(); ++i)
{
rapidjson::Document *sub_ptr = subs[i];
delete sub_ptr;
}
subs.clear();
return 0;
}
x2)rapidjson的schema特性使用示例
#include <rapidjson/document.h>
#include <rapidjson/schema.h>
#include <rapidjson/stringbuffer.h>
int main()
{
std::string str = "\{\"aaa\":111,\"aaa\":222}"; // "\{\"aaa\":111,\"a\":222}"
#if 0
std::string schema_str = "{\"type\":\"object\",\"properties\":{\"aaa\":{\"type\":\"integer\"},\"bbb\":{\"type\":\"string\"}},\"required\":[\"aaa\",\"bbb\"]}";
#else
std::string schema_str = "{\"type\":\"object\",\"properties\":{\"aaa\":{\"type\":\"integer\"},\"bbb\":{\"type\":\"integer\"}},\"required\":[\"aaa\",\"bbb\"]}";
#endif
printf("%s\n", str.c_str());
printf("%s\n", schema_str.c_str());
rapidjson::Document doc;
rapidjson::Document schema_doc;
schema_doc.Parse(schema_str.c_str());
doc.Parse(str.c_str());
rapidjson::SchemaDocument schema(schema_doc);
rapidjson::SchemaValidator validator(schema);
if (doc.Accept(validator))
{
printf("data ok\n");
}
else
{
rapidjson::StringBuffer sb;
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
printf("Invalid schema: %s\n", sb.GetString());
printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
printf("Invalid document: %s\n", sb.GetString());
}
return 0;
}
*) 特別注意rapidjson::Document可以為object, array, number, string, boolean, null中任意一種類型
只有為object時才可以調用HasMember等與object有關的方法
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
std::string str;
rapidjson::Document doc;
doc.Parse(argv[1]);
if (doc.HasParseError())
printf("parse error\n");
// 注意doc可為object, array, number, string, boolean, null中任意一種類型
if (!doc.IsObject())
printf("not object\n");
else
{
printf("parse ok\n");
if (doc.IsNumber())
printf("%d\n", doc.GetInt());
// doc為object類型時,才能調用HasMember
if (doc.HasMember("x"))
printf("has x\n");
else
printf("without x\n");
}
return 0;
}
遍歷成員:
rapidjson::Value value;
。。。
for (rapidjson::Value::ConstMemberIterator iter = value.MemberBegin(); iter!=value.MemberEnd(); ++iter)
{
const rapidjson::Value& name_json = iter->name; // 這個必須是字符串
const rapidjson::Value& value_json = iter->value; // 這個可以為對象、數組等
printf("%s\n", name_json.GetString());
}