개발/C++

JsonCpp 사용법

박오이님 2022. 2. 4. 01:42

먼저, JsonCPP 라이브러리 사용법을 설명하기 전에 앞서 되새겨야 하는 게 있다.
`개발자는 코드를 그대로 베껴오는 게 아니라, 내 것으로 만들고 사용해야 한다`

사실 JsonCPP 사용법은 StackOverflow나 다른 블로그에 엄청 많이 올라와있다.
그래서 필자도 예제 코드를 복붙 해서 변수명만 바꿔서 쓰고 있었지....

그래서 JsonCPP 라이브러리 사용법을 통해서 내 것으로 만들려는 노력과 연습을 하고 개발하려고 합니다.
Case 3가지에 대해서 예제코드를 작성하려고 합니다.

먼저, main문 아래와 같다.

#include <iostream>
#include <fstream>
#include <json/json.h>

int main(int argc, char* argv[])
{
	_CrtMemState memoryState = { 0 };
	_CrtMemCheckpoint(&memoryState);
	{
		_ASSERTE(true == case1());
		_ASSERTE(true == case2());
		_ASSERTE(true == case3());
	}
	_CrtMemDumpAllObjectsSince(&memoryState);

	return 0;
}


Case 1. Json 객체를 생성하고, 파일에 쓰는 Case
해당 케이스는 다양한 방법이 있다. 그러나, 내가 이해한 방법으로 예제 코드를 작성하도록 한다.
Json 객체를 생성하고, 그 Json 객체를 파일에 쓰는 방법이다.

bool case1()
{
	Json::Value epl_table;
	epl_table["team"] = "arsenal";
	epl_table["played"] = 21;
	epl_table["Won"] = 11;
	epl_table["Drawn"] = 3;
	epl_table["Lost"] = 7;

	//
	//	해당 방법은 여러가지가 있다.
	//
	Json::Value root;
	root["Manager"] = "Mikel Arteta";
	root["Captain"] = "N/A";
	root["Vice_Captain"] = "Alexandre Lacazette";
	epl_table["squad"] = root;

	//
	//	위 결과와 같다.
	//	코딩 스타일의 차이일까?
	//
	//epl_table["squad"]["Manager"] = "Mikel Arteta";
	//epl_table["squad"]["Captain"] = "N/A";
	//epl_table["squad"]["Vice_Captain"] = "Alexandre Lacazette";

	//
	//	list 형태 추가
	//
	epl_table["record"].append("2003-04");
	epl_table["record"].append("2001-02");
	epl_table["record"].append("1997-98");

	epl_table["test"] = "remove";

	//
	//	String 으로 변환
	//
	std::string json_to_str = epl_table.toStyledString();
	std::cout << json_to_str << std::endl;

	std::ofstream outfile("arsenal.json", std::ios::out);
	if (true != outfile.is_open())
	{
		std::cout << "File Opne Failed." << std::endl;
		return false;
	}

	// outfile << epl_table;
	outfile << json_to_str;
	outfile.close();

	return true;
}

Case 2. 파일을 읽고, Json 객체로 변환하는 Case

bool case2()
{
	//
	//	Json File 읽기
	//
	std::ifstream infile("arsenal.json", std::ios::in);
	if (true != infile.is_open())
	{
		std::cout << "File Opne Failed." << std::endl;
		return false;
	}

	//
	//	File 내용을 Json 객체로 변환
	//
	Json::Value root;
	infile >> root;
	infile.close();

	//
	//	Json 객체 접근
	//
	std::cout << root["team"].asString() << std::endl;
	//
	//	키 접근 시, 에러방지를 위해 이렇게 접근하면 어떨까?
	//
	if (true == root.isMember("played"))
	{
		std::cout << root["played"].asInt() << std::endl;
	}
	if (true != root.isMember("supporters"))
	{
		std::cout << "supporters not exists" << std::endl;
	}

	//
	//	Json 객체 -> String으로 변환
	//
	std::string json_to_str = root.toStyledString();
	std::cout << json_to_str << std::endl;

	return true;
}


case 3. Json 파일을 읽고, 추가/수정/제거 한 뒤, 파일을 업데이트 하는 Case

bool case3()
{
	//
	//	Json File 읽기
	//
	std::ifstream infile("arsenal.json", std::ios::in);
	if (true != infile.is_open())
	{
		std::cout << "File Opne Failed." << std::endl;
		return false;
	}

	//
	//	File 내용을 Json 객체로 변환
	//
	Json::Value root;
	infile >> root;
	infile.close();

	//
	//	Value 수정 및 추가
	//
	if (true == root.isMember("Lost"))
	{
		root["Lost"] = 0;
	}

	if (true == root.isMember("squad"))
	{
		if (true == root["squad"].isMember("Captain"))
		{
			root["squad"]["Captain"] = "Kieran Tierney";
		}
	}

	root["supporters"] = "Gunners";
	if (true == root.isMember("record"))
	{
		root["record"].append("2021-22");
	}

	//
	//	삭제
	//
	if (true == root.isMember("test"))
	{
		root.removeMember("test");
	}

	//
	//	Json 객체 -> String으로 변환
	//
	std::string json_to_str = root.toStyledString();
	std::cout << json_to_str << std::endl;

	//
	//	파일 저장
	//
	std::ofstream outfile("arsenal.json", std::ios::out);
	if (true != outfile.is_open())
	{
		std::cout << "File Opne Failed." << std::endl;
		return false;
	}

	// outfile << epl_table;
	outfile << json_to_str;
	outfile.close();

	return true;
}


결과물은 한 번 돌려보면 좋을 것 같다.
필자는 아스날 팬이라서, 아스날 위주로 했다. 토트넘 팬이 있다면, 죄송합니다.

감사합니다.