C++ 언어로 객체를 JSON 데이터로 직렬화하고 다시 스트링으로부터 역직렬화 하는 방법을 알아본다.
Modern C++을 이용해서 JSON 데이터를 효과적으로 다루는 다음 공개 소스 코드를 사용한다.
https://github.com/nlohmann/json
nlohmnn json의 경우 header-only 라이브러리로 include 폴더 내의 json.hpp만 포함시키면 링크 없이 바로 적용할 수 있다.
json_define.h
#pragma once
#ifndef _JSON_H_
#define _JSON_H_
#include <nlohmannjson/json.hpp>
using namespace nlohmann;
#endif // !_JSON_H_
일반 객체를 직렬화 하기 Serialize An Object
struct IngredientInfo
{
int calories;
float carbohydrate;
float protein;
float fat;
};
struct Product
{
int code;
std::string tag;
IngredientInfo ingredient;
std::map<std::string, std::string> product_date;
};
직렬화 Serialize
위 정의를 가진 Product 객체를 JSON 스트링으로 변환하는 방법을 알아본다.
각 구조체 정의에 멤버 함수로 json 객체를 반환하는 to_json()를 정의한다.
struct IngredientInfo
{
int calories;
float carbohydrate;
float protein;
float fat;
json to_json()
{
json jobject;
jobject["calories"] = calories;
jobject["carbohydrate"] = carbohydrate;
jobject["protein"] = protein;
jobject["fat"] = fat;
return jobject;
}
};
struct Product
{
int code;
std::string tag;
IngredientInfo ingredient;
std::map<std::string, std::string> product_date;
json to_json()
{
json jobject;
jobject["code"] = code;
jobject["tag"] = tag;
jobject["ingredient"] = ingredient.to_json();
json product_date_jobject;
for (auto& kv : product_date)
{
product_date_jobject[kv.first] = kv.second;
}
jobject["product_date"] = product_date;
return jobject;
}
};
JSON 스트링으로 덤프
json 객체의 dump()를 이용하여 JSON 스트링을 만들어낼 수 있다.
첫번째 인자는 기본적으로 -1을 사용하는데 0이상 값을 사용하면 새로운 키에 대해 \n newline을 사용하고
각 키 indent에 양의 값만큼 space를 적용시킨다. 4를 사용하면 다음 결과를 얻는다.
static void Example()
{
Product proudct;
proudct.code = 230111;
proudct.tag = "meat";
IngredientInfo info;
info.calories = 463;
info.carbohydrate = 237.2f;
info.protein = 41.5f;
info.fat = 12.4f;
proudct.ingredient = info;
proudct.product_date["production_date"] = "2021-03-11";
proudct.product_date["expiry_date"] = "2021-03-23";
auto jobject = proudct.to_json();
auto jsonStr = jobject.dump(4); // tab space size
std::cout << jsonStr << std::endl;
}
JSON 스트링으로 부터 객체 만들기 Deserialize
정적 함수로 각 구조체에 객체를 만들어내는 함수를 정의해준다.
struct IngredientInfo
{
// ...
static IngredientInfo from_json(const json& jobject)
{
IngredientInfo info;
info.calories = jobject.at("calories").get<int>();
info.carbohydrate = jobject.at("carbohydrate").get<float>();
info.protein = jobject.at("protein").get<float>();
info.fat = jobject.at("fat").get<float>();
return info;
}
}; // IngredientInfo
struct Product
{
//...
static Product from_json(const json& jobject)
{
Product product;
product.code = jobject.at("code").get<int>();
product.tag = jobject.at("tag").get<std::string>();
product.ingredient = IngredientInfo::from_json(jobject["ingredient"]);
const json& product_date_jobject = jobject["product_date"];
for (auto& item : product_date_jobject.items())
{
product.product_date[item.key()] = item.value().get<std::string>();
}
return product;
}
}; // Product
위 정의한 from_json 함수로 객체를 역직렬화하여 복원 가능하다.
auto product_deserialized = Product::from_json(jobject);
PrintProduct(product_deserialized);