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,"name":"zhangsan"}]} void x6() { rapidjson::Document document; std::string str = "{}"; // 这个是必须的,且不能为"",否则Parse出错 document.Parse(str.c_str()); // 新增成员count document.AddMember("count",document.GetAllocator()); // 新增数组成员 rapidjson::Value array(rapidjson::kArrayType); rapidjson::Value object(rapidjson::kObjectType); // 数组成员 object.AddMember("id",1,document.GetAllocator()); object.AddMember("name","zhangsan",document.GetAllocator()); // 注意下面用法编译不过: //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()); 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,"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",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()); } int main() { x1(); x2(); x3(); x4(); x5(); x6(); x7(); x8(); 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::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,"%"PRId64,child.GetInt64()); } else if (child.IsUint()) { snprintf(str,"%u",child.GetUint()); } else if (child.IsUint64()) { snprintf(str,"%"PRIu64,child.GetUint64()); } else if (child.IsDouble()) { snprintf(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; }