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;
- }