本節主要介紹RapidJson是如何使用的。
(1)RapidJson是什么
RapidJson是一個跨平台的c++的json的解析器和生成器; 相比較jsoncpp庫,RapidJson只有頭文件,容易安裝; RapidJSON 不依賴STL和boost等外部庫獨立; 只使用如下文件:<cstdio>, <cstdlib>, <cstring>, <inttypes.h>, <new>, <stdint.h>;
高性能,使用模版及內聯函數去降低函數調用開銷、內部經優化的 Grisu2 及浮點數解析實現、可選的 SSE2/SSE4.2 支持.
(2)RapidJson使用范例(DOM解析json字符串並修改json中指定元素的值)
#include <iostream> #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h"
using namespace std; using namespace rapidjson; int main(int argv ,char *argc[]) { //1.把JSON解析至DOM
const char * strJson = "{\"key1\":\"value1\",\"key2\":\"value2\",\"key3\":100}"; Document doc; doc.Parse(strJson); cout<< strJson << endl; //2.利用DOM作出修改
Value& v1 = doc["key2"]; v1="value_modify"; //v1.SetString("value_modify");
Value& v2 = doc["key3"]; v2.SetInt(v2.GetInt()+1); //SetString() //SetBool() //SetUint() //SetInt64() //SetUInt64() //SetDouble() //SetFloat() //SetArray() //SetObject() //SetNull() //3.將DOM stringfy 為json
StringBuffer buffer; Writer<StringBuffer> writer(buffer); doc.Accept(writer); cout<< buffer.GetString() << endl; return 0; }
{"key1":"value1","key2":"value2","key3":100} {"key1":"value1","key2":"value_modify","key3":101}
(3)文件對象模型(Document Object Model, DOM)API
文件對象模型,在RapidJson中廣泛的使用。
1.構建json value到DOM:
#include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h"
using namespace std; using namespace rapidjson; int main(int argv ,char *argc[]) { // 1.准備數據
string name = "MenAngel"; string gender = "boy"; int age = 23; vector<string> hobbys = {"語文","數學","英語"}; map<string,double> score ={{"語文",80},{"數學",90},{"英語",100}}; // 2.初始化DOM
StringBuffer strBuffer; Writer<StringBuffer> writer(strBuffer); //2.1 根DOM開始
writer.StartObject(); writer.Key("name"); writer.String(name.c_str()); writer.Key("gender"); writer.String(gender.c_str());
writer.Key("age");
writer.Int(age); writer.Key("hobby"); writer.StartArray(); for(auto &item : hobbys) { writer.String(item.c_str()); } writer.EndArray(); writer.Key("scores"); writer.StartObject(); for(auto &item : scores) { writer.Key((item.first).c_str()); writer.Double(item.second); } writer.EndObject(); //2.2 根DOM結束
writer.EndObject(); //3.將上述DOM組織的json數據寫入json.txt文件
string outFileName = "json.txt"; ofstream outfile(outFileName,std::ios::trunc); outfile<<strBuffer.GetString()<<endl; outfile.flush(); outfile.close(); return 0; }
{"name":"MenAngel","gender":"boy","age":23,"hobbys":["語文","數學","英語"],"scores":{"數學":90.0,"英語":100.0,"語文":80.0}}
2.構建Json Value到DOM
#include <iostream> #include <fstream> #include <vector> #include <map> #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h"
using namespace std; using namespace rapidjson; int main(int argv ,char *argc[]) { // 1.准備數據
string name = "MenAngel"; string gender = "boy"; int age = 23; vector<string> hobbys = {"語文","數學","英語"}; map<string,double> scores ={{"語文",80},{"數學",90},{"英語",100}}; //2.初始化DOM
Document doc; Document::AllocatorType& allocator = doc.GetAllocator(); doc.SetObject();//實例化一個GenericValue到根DOM
Value tempValue1; tempValue1.SetString(name.c_str(),allocator); doc.AddMember("name",tempValue1,allocator); Value tempValue2(rapidjson::kObjectType); tempValue2.SetString(gender.c_str(),allocator); doc.AddMember("gender",tempValue2,allocator); doc.AddMember("age",age,allocator); Value tempValue3(kArrayType); for(auto hobby:hobbys) { Value hobbyValue(kStringType); hobbyValue.SetString(hobby.c_str(),allocator); tempValue3.PushBack(hobbyValue,allocator); } doc.AddMember("hobbys",tempValue3,allocator); Value tempValue4(kObjectType); tempValue4.SetObject(); for(auto score : scores) { Value scoreValue(kNumberType); //cout<<score.second;
scoreValue.SetInt(score.second); Value scoreName(kStringType); scoreName.SetString(score.first.c_str(),allocator); tempValue4.AddMember(scoreName,scoreValue,allocator); } doc.AddMember("scores",tempValue4,allocator); StringBuffer strBuffer; Writer<StringBuffer> writer(strBuffer); doc.Accept(writer); string outFileName = "json.txt"; ofstream outfile(outFileName,std::ios::trunc); outfile<<strBuffer.GetString()<<endl; outfile.flush(); outfile.close(); return 0; }
{"name":"MenAngel","gender":"boy","age":23,"hobbys":["語文","數學","英語"],"scores":{"數學":90.0,"英語":100.0,"語文":80.0}}
3.RapidJSon查詢
#include <iostream> #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h"
using namespace std; using namespace rapidjson; int main(int argv,char *argc[]) { //1.構建json
const char * strJson = "{\"name\":\"MenAngel\",\"age\":23,\"hobbys\":[\"語文\",\"數學\",\"英語\"]}"; Document doc; doc.Parse(strJson); StringBuffer strBuffer; Writer<StringBuffer> writer(strBuffer); doc.Accept(writer); cout<<strBuffer.GetString()<<endl; //2.查詢json值
cout<<"遍歷方法一:"<<endl; int count = doc.MemberCount(); cout<<"doc 的屬性成員有 "<<count<<"個!"<<endl; static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" }; int i = 0; for(Value::MemberIterator iter = doc.MemberBegin();iter != doc.MemberEnd();++iter) { cout<<++i<<".property "<<iter->name.GetString()<<" is "<<kTypeNames[iter->value.GetType()]<<endl; if(iter->value.GetType() == 4) { //3.遍歷Array
for(auto &item : iter->value.GetArray()) //IsBool、IsObject、IsInt、IsNull、IsNumber、IsDouble
if(item.IsString()) cout<<"item = "<<item.GetString()<<endl; } } //4.查詢某個成員是否存在
Value::ConstMemberIterator it = doc.FindMember("scores"); if(it != doc.MemberEnd()) cout<<"Has Finded!"<<endl; else cout<<"Not Finded!"<<endl; //5.遍歷doc的所有成員
cout<<"遍歷方法二:"<<endl; for(auto &m :doc.GetObject()) { cout<<"Has member :"<<m.name.GetString()<<" = "; if(m.value.IsString()) cout<<m.value.GetString()<<endl; if(m.value.IsInt()) cout<<m.value.GetInt()<<endl; if(m.value.IsBool()) cout<<m.value.GetBool()<<endl; if(m.value.IsArray()) cout<<"is array"<<endl; } return 0; }
{"name":"MenAngel","age":23,"hobbys":["語文","數學","英語"]} 遍歷方法一: doc 的屬性成員有 3個!
1.property name is String 2.property age is Number 3.property hobbys is Array item = 語文 item = 數學 item = 英語 Not Finded! 遍歷方法二: Has member :name = MenAngel Has member :age = 23 Has member :hobbys = is array
4.RapidJson屬性獲取
#include <iostream> #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h"
using namespace std; using namespace rapidjson; int main(int argv,char *argc[]) { //1.構建json
const char * strJson = "{\"name\":\"MenAngel\",\"age\":23,\"hobbys\":[\"語文\",\"數學\",\"英語\"]}"; Document doc; doc.Parse(strJson); StringBuffer strBuffer; Writer<StringBuffer> writer(strBuffer); doc.Accept(writer); cout<<strBuffer.GetString()<<endl; //2.DOM根是一個對象
if(doc.IsObject()) cout<<"doc is object!"<<endl; //3.doc不為j空
if(!doc.IsNull()) { cout<<"doc is not null!"<<endl; } Document document; if(document.IsNull()) { cout<<"document is null!"<<endl; cout<<"Set Object"<<endl; document.SetObject(); } if(!document.IsNull()) cout<<"document is not null!"<<endl; //4.DOM 的大小.
cout<<"doc.MemmberCount() = "<<doc.MemberCount()<<endl; //5.增加HasMember判斷防止斷言錯誤
if(doc.HasMember("hobbys") && !doc["hobbys"].Empty()) cout<<"doc[\"hobbys\"] is not empty!"<<endl; else cout<<"member not exits!"<<endl; //6.取鍵值
Value::ConstMemberIterator iter = doc.FindMember("age"); if(iter != doc.MemberEnd()) { cout<<"Member age is exits!"<<endl; cout<<iter->name.GetString()<<":"<<iter->value.GetInt()<<endl; } //7.Array的大小
cout<<"doc[\"hobbys\"].Capacity() = "<<doc["hobbys"].Capacity()<<endl; //8.字符串的大小 當字符中存在\u0000時strlen會到此截斷
cout<<"doc[\"name\"].length = "<<strlen(doc["name"].GetString())<<endl; cout<<"doc[\"name\"].length = "<<doc["name"].GetStringLength()<<endl; doc.AddMember("test","a\u0000b",doc.GetAllocator()); //只能當test成員存在時才能直接賦值 //doc["test"] = "a\u0000b";
cout<<"doc[\"test\"].length = "<<strlen(doc["test"].GetString())<<endl; cout<<"doc[\"test\"].length = "<<doc["test"].GetStringLength()<<endl; // return 0; }
{"name":"MenAngel","age":23,"hobbys":["語文","數學","英語"]} doc is object! doc is not null! document is null! Set Object document is not null! doc.MemmberCount() = 3 doc["hobbys"] is not empty! Member age is exits! age:23 doc["hobbys"].Capacity() = 3 doc["name"].length = 8 doc["name"].length = 8 doc["test"].length = 1 doc["test"].length = 3
5.RapidJson一些特性
#include <iostream> #include <stdio.h> #include <stdlib.h> #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h"
using namespace std; using namespace rapidjson; int main(int argv,char *argc[]) { //1.構建json
const char * strJson = "{\"name\":\"MenAngel\",\"age\":23,\"hobbys\":[\"語文\",\"數學\",\"英語\"]}"; Document doc; doc.Parse(strJson); StringBuffer strBuffer; Writer<StringBuffer> writer(strBuffer); doc.Accept(writer); cout<<strBuffer.GetString()<<endl; //2.const char *、string、value(kStringType)之間比較大小
if(doc["name"] == "MenAngel") cout<<"(1)doc[\"name\"] equal MenAngel!"<<endl; if(doc["name"].GetString() == string("MenAngel")) cout<<"(2)doc[\"name\"] equal MenAngel!"<<endl; if( 0 == strcmp(doc["name"].GetString(),"MenAngel")) cout<<"(3)doc[\"name\"] equal MenAngel!"<<endl; if(doc["name"].GetString() != "MenAngel") cout<<"(4)不成立!"<<endl; //3.value賦值
Value v;//v is NULL && v is not Object
if(v.IsNull()) cout<<"v is Null()"<<endl; v.SetObject(); if(v.IsObject()) cout<<"v is Object"<<endl; Value tValue(kObjectType);//tValue is not Null,tValue is Object
if(!tValue.IsNull()) cout<<"tVlaue is not NULL!"<<endl; if(tValue.IsObject()) cout<<"tValue is Object"<<endl; //4.轉移語義,避免value深賦值 //AddMember(), PushBack()、賦值均采用深賦值
Value a(123); Value b(456); a = b; if(b.IsNull()) cout<<"b is Null,"<<"a = "<<a.GetInt()<<endl; Value c(kArrayType); Document::AllocatorType& allocator = doc.GetAllocator(); c.PushBack(Value(11), allocator); c.PushBack(Value().SetInt(22), allocator); // fluent API
c.PushBack(Value(33).Move(), allocator); // 轉移語義
cout<<"c.Capacity() = "<<c.Capacity()<<endl; cout<<"c.Size() = "<<c.Size()<<endl; for(auto &m : c.GetArray()) { cout<<"item = "<<m.GetInt()<<endl; } //字符串的容量及大小
cout<<"doc[\"hobbys\"].Size() = "<<doc["hobbys"].Size()<<endl; cout<<"doc[\"hobbys\"].Capacity() = "<<doc["hobbys"].Capacity()<<endl; //5.交換value
Value d(123); Value e("string"); d.Swap(e); if(!d.IsNull() && !e.IsNull()) { cout<<"d is not null,e is not null!"<<endl; cout<<"d = "<<d.GetString()<<" e = "<<e.GetInt()<<endl; } //6.創建string //復制字符串
Value f(kStringType); char str[20] = "My first string!"; f.SetString(str,doc.GetAllocator()); cout<<f.GetString()<<endl; Value g; char buffer[20]; int len = sprintf(buffer, "%s -> %s", "name", "value"); // 動態創建的字符串。
g.SetString(buffer,len,doc.GetAllocator()); //g.SetString(buffer,doc.GetAllocator())
cout<<g.GetString()<<endl; //簡單引用常量字符串
Value h; h.SetString("My third String!");// h = "My thrid String!"
cout<<h.GetString()<<endl; //簡單引用常量l字符串
Value i; const char * tempStr = "my fourth string"; size_t cstr_len = strlen(tempStr); i.SetString(StringRef(tempStr)); //i.SetString(StringRef(tempStr,cstr_len)); //i = StringRef(tempStr,cstr_len) //i = StringRef(tempStr) //i.SetString(tempStr); 不合法
cout<<i.GetString()<<endl; return 0; }
{"name":"MenAngel","age":23,"hobbys":["語文","數學","英語"]} (1)doc["name"] equal MenAngel! (2)doc["name"] equal MenAngel! (3)doc["name"] equal MenAngel! (4)不成立! v is Null() v is Object tVlaue is not NULL! tValue is Object b is Null,a = 456 c.Capacity() = 16 c.Size() = 3 item = 11 item = 22 item = 33 doc["hobbys"].Size() = 3 doc["hobbys"].Capacity() = 3 d is not null,e is not null! d = string e = 123 My first string! name -> value My third String! my fourth string