RapidJson NEXT 김명찬
RapidJson 수 많은 C++ 용 Json library 중 하나. (JsonCpp와 비교하여) 더 작고 더 빠르고 더 가벼움. DOM(document object model) 객체로 만들어 다룸. 다소 헤더파일이 많음. (75KB vs 586KB)
RapidJson Json 호환성 테스트 높을 수록 좋음.
RapidJson String -> 객체 파싱 속도 작을수록 좋음
RapidJson 메모리 사용량 작을수록 좋음 strdup는 string자체를 의미
RapidJson 객체 -> string 바꾸는데 걸린 시간 작을수록 good
RapidJson 들여쓰기와 newline 만들기 걸린 시간 작을수록 good
RapidJson 컴파일된 바이너리의 크기 작을수록 good
RapidJson 자랑은 이정도 하고..
RapidJson - 설치법 https://github.com/miloyip/rapidjson/ Include 폴더의 내용을 본인 Include 폴더에 복사하면 끝. #include "rapidjson/document.h" using namespace rapidjson;
RapidJson – 기본 사용. root 는 오브젝트로 생성됨. Value 클래스로 모든값이 저장됨. #include "rapidjson/document.h" using namespace rapidjson; char json[] = ... Document document; document.Parse(json); char json[] = R"( { "hello": "world", "t" : true, "f" : false, "n" : null, "i" : 123, "pi" : 3.1416, "a" : [1, 2, 3, 4] })";
RapidJson – 기본 사용. root 는 오브젝트로 생성됨. Value 클래스로 모든값이 저장됨.
RapidJson - string char json[] = R"( { "hello": "world", "t" : true, "f" : false, "n" : null, "i" : 123, "pi" : 3.1416, "a" : [1, 2, 3, 4] })"; Document document; document.Parse(json); assert(document.IsObject()); assert(document.HasMember("hello")); assert(document["hello"].IsString() == true); sprintf(json, "%s", document["hello"].GetString()); MultiByteToWideChar(CP_ACP, 0, json, -1, temp, strlen(json)); TextOut(memoryDC, 10, 10, temp, lstrlen(temp));
RapidJson - bool char json[] = R"( { "hello": "world", "t" : true, "f" : false, "n" : null, "i" : 123, "pi" : 3.1416, "a" : [1, 2, 3, 4] })"; Document document; document.Parse(json); assert(document["t"].IsBool()); assert(document["t"].GetBool() == true); sprintf(json, "%s", document["t"].GetBool() ? "True" : "False"); MultiByteToWideChar(CP_ACP, 0, json, -1, temp, strlen(json)); TextOut(memoryDC, 10, 10, temp, lstrlen(temp));
RapidJson - null char json[] = R"( { "hello": "world", "t" : true, "f" : false, "n" : null, "i" : 123, "pi" : 3.1416, "a" : [1, 2, 3, 4] })"; Document document; document.Parse(json); assert(document["n"].IsNull() == true); sprintf(json, "%s", document["n"].IsNull() ? "True" : "False"); MultiByteToWideChar(CP_ACP, 0, json, -1, temp, strlen(json)); TextOut(memoryDC, 10, 10, temp, lstrlen(temp));
RapidJson - number char json[] = R"( { "hello": "world", "t" : true, "f" : false, "n" : null, "i" : 123, "pi" : 3.1416, "a" : [1, 2, 3, 4] })"; Document document; document.Parse(json); assert(document["i"].IsNumber()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true. assert(document["i"].IsInt()); // Alternative (int)document["i"] assert(document["pi"].IsNumber()); assert(document["pi"].IsDouble());
RapidJson - array char json[] = R"( { "hello": "world", "t" : true, "f" : false, "n" : null, "i" : 123, "pi" : 3.1416, "a" : [1, 2, 3, 4] })"; Document document; document.Parse(json); assert(document["a"].IsArray()); // Using a reference for consecutive access // is handy and faster. const Value& a = document["a"]; assert(a.IsArray()); for (SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t { char tmpJson[50]; sprintf(tmpJson ,"a[%d] = %d ", i, a[i].GetInt()); strcat(json, tmpJson); }
RapidJson - array for (SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t { char tmpJson[50]; sprintf(tmpJson ,"a[%d] = %d ", i, a[i].GetInt()); strcat(json, tmpJson); } for (auto itr = a.Begin(); itr != a.End(); ++itr) { char tmpJson[50]; sprintf(tmpJson, "%d ", itr->GetInt()); strcat(json, tmpJson); } SizeType Capacity() const bool Empty() const
RapidJson – typename(enum) static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" }; sprintf(json, "%s", kTypeNames[a.GetType()]); auto tmp = a.GetType(); //typename을 확인하고 싶다면.. auto 위에 마우스 커서를... sprintf(json, "%s", kTypeNames[tmp]); Enum으로 처리됩니다! bool 대신 False, True가 있는 것이 특이하네요..
RapidJson - 검색 auto itr = document.FindMember("hello"); if (itr != document.MemberEnd()) // End() means cannot find sprintf(json, "%s ", itr->value.GetString());
RapidJson - Number JSON은 Number라는 단독 타입으로 숫자를 넘김. 파서가 각 값들의 타입을 결정한다. Checking Obtaining bool IsNumber() N/A bool IsUint() unsigned GetUint() bool IsInt() int GetInt() bool IsUint64() uint64_t GetUint64() bool IsInt64() int64_t GetInt64() bool IsDouble() double GetDouble()
RapidJson – Number 예를들어 x = 123 x = -3,000,000,000 x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true x.IsInt64() == true
RapidJson – string length 예 이 문자열의 길이는 3 입니다. ( ‘a’, ‘\u0000’, ‘b’ ) strlen을 하면 1로 나옵니다. ( \u0000을 null로 인식 ) GetStringLength() 를 사용하면 3이 나옴. alloc한 문자열에서는 성능 향상도 있음. { "s" : "a\u0000b" }
RapidJson - comparision Value 클래스에 != , == 사용 가능 if (document["hello"] == document["n"]) /*...*/; // Compare values if (document["hello"] == "world") /*...*/; // Compare value with literal string if (document["i"] != 123) /*...*/; // Compare with integers if (document["pi"] != 3.14) /*...*/; // Compare with double.
RapidJson – modifying DOM Document d; // Null d.SetObject(); Value v; // Null v.SetInt(10); v = 10; // Shortcut, same as above Value b(true); // calls Value(bool) Value i(-123); // calls Value(int) Value u(123u); // calls Value(unsigned) Value d(1.5); // calls Value(double)
RapidJson - modifying DOM 빈값 생성 Value v; //기본 생성자로 생성한 후에 v.SetObject(); // 빈 Object로 변환함 v.SetArray(); // 빈 Array로 변환함
RapidJson – move sementics!!! 엄청 중요 헐… 속도 때문임. 큰 Object 복사할때는 시간이 겁나 걸린대요. 깊은 복사는 뒤에서 다룹니다. Value a(123); Value b(456); a = b; // b -> Null value, a -> number 123.
RapidJson – create string Document document; Value author; char buffer[10]; int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // 문자열 동적 생성 author.SetString(buffer, len, document.GetAllocator()); memset(buffer, 0, sizeof(buffer)); // author.GetString()는 아직 버퍼가 파괴된 이후에도 // "Milo Yip"를 포함한다.
RapidJson – create string 얕은복사? – 안됨. const char * cstr = getenv("USER"); size_t cstr_len = ...; // 여기서 길이를 측정한다. Value s; // s.SetString(cstr); // 컴파일 되지 않는다. s.SetString(StringRef(cstr)); // ok, 널문자열이며 생명주기가 보장된다. s = StringRef(cstr); // 위와 같다. s.SetString(StringRef(cstr,cstr_len)); // 빠르고, 널 문자열을 포함한다. s = StringRef(cstr,cstr_len); // 위와 같다.
RapidJson – modifying Array Clear() Reserve(SizeType, Allocator&) Value& PushBack(Value&, Allocator&) template <typename T> GenericValue& PushBack(T, Allocator&) Value& PopBack() ValueIterator Erase(ConstValueIterator pos) ValueIterator Erase(ConstValueIterator first, ConstValueIterator last)
RapidJson – modifying Array Value a(kArrayType); Document::AllocatorType& allocator = document.GetAllocator(); for (int i = 5; i <= 10; i++) a.PushBack(i, allocator); // allocator is needed for potential realloc(). a.PushBack("Lua", allocator).PushBack("Mio", allocator);
RapidJson – modify object Value contact(kObject); contact.AddMember("name", "Milo", document.GetAllocator()); contact.AddMember("married", true, document.GetAllocator());
RapidJson – Deep Copy 깊은복사 Document d; Document::AllocatorType& a = d.GetAllocator(); Value v1("foo"); // Value v2(v1); // 허용하지 않는다 Value v2(v1, a); // 카피를 만든다. assert(v1.IsString()); // v1은 문자열이었는데… d.SetArray().PushBack(v1, a).PushBack(v2, a); assert(v1.IsNull() && v2.IsNull()); // 둘다 d로 이동 v2.CopyFrom(d, a); // 전체 도큐먼트를 v2로 카피 assert(d.IsArray() && d.Size() == 2); // d는 손대지 않았다. v1.SetObject().AddMember("array", v2, a); d.PushBack(v1, a);
RapidJson – swap value Value a(123); Value b("Hello"); a.Swap(b); assert(a.IsString()); assert(b.IsInt());
RapidJson 감사합니다. 참고자료 https://github.com/miloyip/rapidjson/ http://miloyip.github.io/rapidjson/md_doc_tutorial.html http://postgame.tistory.com/558