본문 바로가기

개발 노트/C , C++

[C++ Library] JsonCPP vs Rapid Json

반응형

C++ Json Library 사용하기 위해 조사한 결과 크게 2가지가 있다.

JsonCPP 와 RapidJson 라이브러리는 C++ 로 되어있는 라이브러리 중 가장 인기 있는 2가지 인것으로 보인다.


아래는 다른 사람들이 조사한 다른 라이브러리들 비교 정리해놓은 링크이다.


Json Library 선택 하기 위한 요소로는

  1. 커뮤니티 및 예제 코드 수, 사용자 수
  2. Parsing 속도
  3. .cpp .h 파일로 사용가능
  4. Json Member 의 순서 입력 가능 여부
이 정도를 고려했다.
Json Member 순서 조정 가능 여부는 Json 을 사람이 보았을 경우 중요도에 따라 Json member 를 배치하고 싶을 때를 위해서였다.


결론부터 말하자면,나는 RapidJson 을 선택했다.


1. 커뮤니티 및 예제 코드 수, 사용자 수

링크 : https://cpp.libhunt.com/compare-rapidjson-vs-jsoncpp


위 링크에서 보았을 때 선택 요소 1번에서는 RapidJson 의 승리였다.

github 의 Starts 및 Watchers 수가 RapidJson 의 승리다.


2. Parsing 속도

Parsing 속도에서도 Rapidjson 은 13 ms , JsonCPP 는 171 ms 로
RapidJson 의 속도가 10배 이상 빠르다고 나와있다.


3. Header 만으로 사용 가능
이 부분은 JsonCPP, Rapid Json 모두 소스코드로 되어 있었다.

4. Json Member 의 순서를 개발자단에서 조정 가능 여부
JsonCPP 는 순서가 Member 의 알파벳 순서로만 출력이 가능하지만,
RapidJosn 은 개발자가 입력한 Member 순서로 출력이 가능하다.


이 부분이 가장 중점적으로 눈에 띈 부분이다. Json 라이브러리로 설정파일 같은 데이터를 쓰는 경우 개발자가 임의로 설정의 우선순위에 따라 데이터를 입력하고 싶은데 JsonCPP 는 불가능하였다.


따라서, CPP Json Library 로 Rapid Json 을 사용하기로 결정하였다.

아래는 JsonCPP 와 RapidJson 을 조사하면서 정리한 각각의 설치 방법 및 코딩 스타일을 보기 위한 샘플 코드들이다.

JsonCPP


1) 설치 방법

 1. jsoncpp 공식 github 에서 라이브러리 다운로드

]# git clone https://github.com/open-source-parsers/jsoncpp.git

2.  다운로드 설치 , dist 디렉터리에 라이브러리 파일들 생김

]# python ./amalgamate.py

]# tree dist/



위 2단계면 우선 라이브러리 사용에 대한 준비는 끝이다.

컴파일 시 위 3개의 파일만 추가해주면 사용이 가능하다.


2) 사용 예시 (Read Json)


#include "json/json.h"
#include 

#define JSON_FILE "sample.json"

bool ReadFromFile(const char* filename, char* buffer, int len)
{
    FILE* r = fopen(filename, "rb");
    if (NULL == r)
        return false;
    size_t fileSize = fread(buffer, 1, len, r);
    fclose(r);
    return true;
}

int main(int argc, char* argv[])
{
    const int BufferLength = 102400;
    char readBuffer[BufferLength] = {0,};
    if (false == ReadFromFile(JSON_FILE, readBuffer, BufferLength))
        return 0;
    std::string config_doc = readBuffer;
    Json::Value rootr;
    Json::Reader reader;
    bool parsingSuccessful = reader.parse( config_doc, rootr );
    if ( !parsingSuccessful )
    {
        std::cout  << "Failed to parse configuration\n"
            << reader.getFormatedErrorMessages();
        return 0;
    }


    std::cout <<  rootr["Dhcp4"]["control-socket"]["socket-type"].asString() << std::endl;
    return 0;
}


위 코드는 json 파일의 내용을 읽어 특정 Member 를 출력하는 코드이다.

JsonCPP 는 멤버 접근이 위처럼 대괄호로 멤버 접근이 가능하여 코드 가독성이 좋고 간결하다.



Rapid Json


1) 설치 방법

1. git hub 에서 다운로드 

 ]# git clone https://github.com/Tencent/rapidjson/

 2. 라이브러리 설치


]# cd rapidjson
]# git submodule update --init
]# mkdir build
]# cd build
]# cmake;make;



2) 사용 예시


#include "rapidjson/document.h"     // rapidjson's DOM-style API
#include "rapidjson/prettywriter.h" // for stringify JSON
#include 

using namespace rapidjson;
using namespace std;

int main(int, char*[]) {
    const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
    Document document;  // Default template parameter uses UTF8 and MemoryPoolAllocator.
    // In-situ parsing, decode strings directly in the source string. Source must be string.
    char buffer[sizeof(json)];
    memcpy(buffer, json, sizeof(json));
    if (document.ParseInsitu(buffer).HasParseError())
        return 1;

    printf("\nParsing to document succeeded.\n");

    printf("\nAccess values in document:\n");
    assert(document.IsObject());    // Document is a JSON value represents the root of DOM. Root can be either an object or array.

    assert(document.HasMember("hello"));
    assert(document["hello"].IsString());
    printf("hello = %s\n", document["hello"].GetString());

    // Since version 0.2, you can use single lookup to check the existing of member and its value:
    Value::MemberIterator hello = document.FindMember("hello");
    assert(hello != document.MemberEnd());
    assert(hello->value.IsString());
    assert(strcmp("world", hello->value.GetString()) == 0);
    (void)hello;

    assert(document["t"].IsBool());     // JSON true/false are bool. Can also uses more specific function IsTrue().
    printf("t = %s\n", document["t"].GetBool() ? "true" : "false");

    assert(document["f"].IsBool());
    printf("f = %s\n", document["f"].GetBool() ? "true" : "false");

    printf("n = %s\n", document["n"].IsNull() ? "null" : "?");

    assert(document["i"].IsNumber());   // Number is a JSON type, but C++ needs more specific type.
    assert(document["i"].IsInt());      // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
    printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]

    assert(document["pi"].IsNumber());
    assert(document["pi"].IsDouble());
    printf("pi = %g\n", document["pi"].GetDouble());

    {
        const Value& a = document["a"]; // Using a reference for consecutive access is handy and faster.
        assert(a.IsArray());
        for (SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t.
            printf("a[%d] = %d\n", i, a[i].GetInt());

        int y = a[0].GetInt();
        (void)y;

        // Iterating array with iterators
        printf("a = ");
        for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
            printf("%d ", itr->GetInt());
        printf("\n");
    }
}


위 코드는 rapidjson 에서 제공하는 tutorial 의 Json Read 파트 일부를 발췌한 것이다.

샘플코드에서 알 수 있듯이 rapidjson 라이브러리는 assert 를 굉장히 좋아한다.



반응형