C++

[C++] libcurl (2) JSON 데이터 다루기

로파이 2022. 4. 17. 23:00

C++ 언어로 객체를 JSON 데이터로 직렬화하고 다시 스트링으로부터 역직렬화 하는 방법을 알아본다.

 

Modern C++을 이용해서 JSON 데이터를 효과적으로 다루는 다음 공개 소스 코드를 사용한다.

https://github.com/nlohmann/json

 

GitHub - nlohmann/json: JSON for Modern C++

JSON for Modern C++. Contribute to nlohmann/json development by creating an account on GitHub.

github.com

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);


- 관련 문서
https://json.nlohmann.me/api/basic_json/dump/