오픈 소스 C 라이브러리인 멜론의 JSON 파서를 살펴보고, 그 특징을 잘 알려진 cJSON과 비교하여 차이점과 유사점을 이해합니다. 오픈 소스 C 라이브러리 멜론의 JSON 파서를 소개합니다.
많은 독자들이 cJSON에 대해 들어보거나 사용해보았을 것이라 생각합니다. 매우 유명한 오픈소스 프로젝트입니다. 이 글에서는 cJSON과 멜론의 JSON 구성요소를 비교하고자 합니다.
인코딩
다음과 같은 JSON을 구축하려고 합니다:
{
"name": "Awesome 4K",
"resolutions": [
{
"width": 1280,
"height": 720
},
{
"width": 1920,
"height": 1080
},
{
"width": 3840,
"height": 2160
}
]
}
그럼 먼저 cJSON 버전을 살펴보도록 하겠습니다:
#include <stdio.h>
#include <cjson/cJSON.h>
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor_with_helpers(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *resolutions = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
{
goto end;
}
resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
if (resolutions == NULL)
{
goto end;
}
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
cJSON *resolution = cJSON_CreateObject();
if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
{
goto end;
}
if (cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
int main(void)
{
char *p;
p = create_monitor_with_helpers();
printf("%s\n", p);
return 0;
}
다음으로 멜론을 살펴보도록 하겠습니다:
#include <stdio.h>
#include "mln_json.h"
#include "mln_log.h"
static mln_string_t *generate(void)
{
mln_json_t j;
mln_string_t *ret;
mln_json_init(&j);
mln_json_generate(&j, "{s:s,s:[{s:d,s:d},{s:d,s:d},{s:d,s:d}]}", \
"name", "Awesome 4K", "resolutions", "width", 1280, "height", 720, \
"width", 1920, "height", 1080, "width", 3840, "height", 2160);
ret = mln_json_encode(&j);
mln_json_destroy(&j);
return ret;
}
int main(void)
{
mln_string_t *p;
p = generate();
mln_log(none, "%S\n", p);
return 0;
}
후자의 코드는 매우 짧고, 생성될 JSON 형식을 직관적으로 확인할 수 있습니다.
디코드
다음과 같은 JSON이 있습니다:
{
"name": "Awesome 4K",
"resolutions": [
{
"width": 1280,
"height": 720
}
]
}
먼저 디코딩에 대해 알아보겠습니다, cJSON:
#include <stdio.h>
#include <cjson/cJSON.h>
int supports_full_hd(const char * const monitor)
{
const cJSON *resolution = NULL;
const cJSON *resolutions = NULL;
cJSON *monitor_json = cJSON_Parse(monitor);
if (monitor_json == NULL)
return -1;
resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
cJSON_ArrayForEach(resolution, resolutions)
{
cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
return width->valuedouble;
}
cJSON_Delete(monitor_json);
return -1;
}
int main(void)
{
char p[] = "{\"name\":\"Awesome 4K\",\"resolutions\":[{\"width\":1280,\"height\":720}]}";
int i = supports_full_hd(p);
printf("%d\n", i);
return 0;
}
다음은 멜론입니다:
#include <stdio.h>
#include "mln_json.h"
#include "mln_log.h"
static int handler(mln_json_t *j, void *data)
{
return (int)mln_json_number_data_get(j);
}
static int parse(mln_string_t *p)
{
mln_json_t j;
mln_string_t exp = mln_string("resolutions.0.width");
mln_json_decode(p, &j);
return mln_json_parse(&j, &exp, handler, NULL);
}
int main(void)
{
mln_string_t p = mln_string("{\"name\":\"Awesome 4K\",\"resolutions\":[{\"width\":1280,\"height\":720}]}");
int i = parse(&p);
mln_log(none, "%d\n", i);
return 0;
}
이번에는 두 코드 간의 행 수에 큰 차이가 없습니다. 하지만 후자의 구현에서는 객체 유형의 저장 데이터 구조로 적흑색 트리를 사용합니다. 따라서 키가 많은 객체를 대면했을 때 검색 효율이 매우 안정적일 것입니다.
결론
멜론의 JSON 구성 요소는 주로 사용자가 JSON을 인코딩하고 디코딩할 수 있도록 다음과 같은 네 가지 기능을 제공합니다:
mln_json_decode JSON 문자열을 JSON 구조 노드로 디코딩합니다.
mln_json_parse는 주어진 표현식에 기초하여 디코딩된 JSON 구조로부터 해당 JSON 서브 노드를 획득하는 방법입니다.
mln_json_generate는 지정된 형식 정보를 기반으로 JSON 구조를 구축합니다.
mln_json_encode는 생성된 JSON 구조를 기반으로 JSON 문자열을 생성합니다.
이 네 가지 기능을 바탕으로 JSON을 쉽게 인코딩하고 디코딩할 수 있어 개발자들이 쉽게 사용하고 코드 유지 보수를 할 수 있습니다.
'SW > C++' 카테고리의 다른 글
C++ : shared_ptr 와 weak_ptr : 개념, 차이, 활용법, 예제, 구현 (0) | 2020.05.10 |
---|---|
C++ : weak_ptr : 약한 참조 개념, 사용법, 예제, 구현 (0) | 2020.05.09 |
C++ : shared_ptr : 개념, 예제, 사용법, 구현 (0) | 2020.05.08 |
C++ : 자동 메모리 관리, 가비지 컬렉션, 참조 카운트 : 개념, 관계, 장단점 (0) | 2020.05.07 |
C++ : unique_ptr : 배스트 프렉티스, 기본 예제, 활용 방법, 동작 방식 (0) | 2020.05.06 |