rapidjson常规用法
官方文档地址: rapidjson文档
目录
1. rapidjson 安装
rapidjson下载之后,将原项目中include文件夹拷贝到自己项目的include文件夹下即可,不需要再编译为静态库或动态库。
2. 序列化与反序列化
2.1生成json对象
例如目标json格式为:
{
"env_name": "测试",
"node_name": "centos7",
"dns_time": 0.2,
"max_wait_time": 5,
"redirect": true,
"target_link": [
"1.0.0.0:1410",
"1.0.0.1:1411"
],
"redirect_details": {
"bj": "0.0.0.0",
"sh": "0.0.0.1"
},
"null_obj":{}
}
生成json对象:
void product(rapidjson::Document& doc){
// 相比于jsoncpp,rapidjson的内存分配是需要显示给出的;构造doc时也可以传入一个分配器
// 而jsoncpp内部是大多是调用new delete进行内存分配
// 这也就说明,allocator作为Document类的属性,在析构的时候才会释放,若是外部传入的参数需要注意多次释放的问题
rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> & allocator = doc.GetAllocator();
doc.SetObject();
doc.AddMember("env_name", "测试", allocator);
doc.AddMember("node_name", "centos7", allocator);
doc.AddMember("dns_time", 0.2, allocator);
doc.AddMember("max_wait_time", 5, allocator);
doc.AddMember("redirect", true, allocator);
// 添加数组
rapidjson::Value arr(rapidjson::kArrayType);
arr.PushBack("1.0.0.0:1410",allocator);
arr.PushBack("1.0.0.0:1410",allocator);
doc.AddMember("target_link", arr, allocator);
// 添加对象
rapidjson::Value obj(rapidjson::kObjectType);
obj.AddMember("bj","0.0.0.0",allocator);
obj.AddMember("sh","0.0.0.1",allocator);
doc.AddMember("redirect_details", obj, allocator);
doc.AddMember("null_obj", rapidjson::kObjectType, allocator);
}
2.2 获取json对象的值
- 根据key获取值
void read_json(rapidjson::Document& doc){
if(doc.HasMember("env_name") && doc["env_name"].IsString()){
std::clog << "env_name:" << doc["env_name"].GetString() << std::endl;
}
#ifdef TEST
// jsoncpp对于不存在的key,可以使用[]操作符,返回的是null类型
// rapidjson的[]操作符返回的是引用,对于不存在的key,直接引用会core
// rapidjson::Value& tmp = doc["env_name_"];
//std::clog << doc["env_name_"].GetString() << std::endl;
#endif
if(doc.HasMember("target_link") && doc["target_link"].IsArray()){
for(auto itr = doc["target_link"].Begin(); itr!=doc["target_link"].End();++itr){
std::clog << "target_link:" << itr->GetString() << std::endl;
}
}
}
- 类jsonpath抽取
相比于jsoncpp的Path类,rapidjson中提供了更丰富的Point模板实例,可以根据Point进行抽取和生成
// Point
rapidjson::Pointer point("/target_link/0");
std::clog << "point value=" << point.Get(doc)->GetString() << std::endl;
2.3 写入字符串
rapidjson是漠然支持UTF8编码
- 由Json对象生成字符串
void writer_str(rapidjson::Document& doc, bool style = false){
rapidjson::StringBuffer buf;
if(!style){
rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
doc.Accept(writer);
std::clog << buf.GetString() << std::endl;
return;
}
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
doc.Accept(writer);
std::clog << buf.GetString() << std::endl;
}
- 直接生成json字符串
std::string product_direct(){
rapidjson::StringBuffer buf;
// rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
writer.StartObject();
writer.Key("env_name"); writer.String("测试");
writer.Key("node_name"); writer.String("centos7");
writer.Key("dns_time"); writer.Double(0.2);
writer.Key("max_wait_time"); writer.Int(5);
writer.Key("redirect"); writer.Bool(true);
writer.Key("target_link");
writer.StartArray();
writer.String("1.0.0.0:1410");
writer.String("1.0.0.0:1410");
writer.EndArray();
writer.Key("redirect_details");
writer.StartObject();
writer.Key("bj"); writer.String("0.0.0.0");
writer.Key("sh"); writer.String("0.0.0.1");
writer.EndObject();
writer.Key("null_obj");
writer.StartObject();
writer.EndObject();
writer.EndObject();
return buf.GetString();
}
2.4 解析json文件
rapidjson解析文件官方说明: 文件流,提供了多种流的输入方式, 例如使用iostream的包装类 ISatreamWrapper.
void parse_file(const std::string file_name){
std::ifstream file(file_name, std::ios::in | std::ios::binary);
if(!file.is_open()) return;
// Document可以指定编码,默认未UTF8
// rapidjson::GenericDocument<rapidjson::UTF16<>> utr16_doc;
rapidjson::Document doc;
rapidjson::IStreamWrapper input_stream(file);
doc.ParseStream(input_stream);
if(doc.HasParseError()) return;
std::clog << doc.GetString() << std::endl;
}
3. rapidjson内存分配器
源码中的allocators.h
文件中描述了内存分配相关内容。
- MemoryPoolAllocator 采用引用计数共享数据,使用带有头节点的链表管理内存节点,默认每个节点大小64K
- 初始化时 shared_节点和 ChunkHeader节点在内存上是连续的;后续申请内存时,到shared_指向的Chunk中申请,若是大小溢出,则申请新的节点,新节点挂在链表头部,shared_指针指向最新节点。