본문 바로가기
IT/programming

[C/C++] C++ JSON parser example, C언어 JSON 파서 예제, rapidjson

by 어느해겨울 2022. 1. 17.

C++ JSON parser example

 

본 json_parser 라이브러리는 rapidjson을 활용한 wrapper이다. 

이미 그 자체로 훌륭한 JSON parser 인 rapidjson은 소스코드가 아닌 헤더로만 구성되어있고 사용자의 역량에 따라 코드 표현이 천차만별이라 같은 선언, 같은 메서드, 같은 출력을 보장하기 위해(공용화) wrapper class를 만들게 되었다.

 

* rapidjson 홈페이지, tutorial이 무척 잘되어있다.

https://rapidjson.org/

 

RapidJSON: Main Page

A fast JSON parser/generator for C++ with both SAX/DOM style API Tencent is pleased to support the open source community by making RapidJSON available. Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Build status Introduction RapidJSON

rapidjson.org

본인도 본인이 만든 json_parser class를 주로 사용하지만 가끔 세부적인 handling이 필요할땐 rapidjson의 기능을 직접 사용한다.

 

소스코드와 라이브러리 빌드, 샘플 파일은 아래 경로에 업로드 되어 있으니 참고하자.

* github 공유

 

https://github.com/muabow/home/tree/main/library/cpp/lib_json_parser

 

GitHub - muabow/home: C/C++, PHP, GO source/library

C/C++, PHP, GO source/library. Contribute to muabow/home development by creating an account on GitHub.

github.com

 

구성

1. include/json_parser.h (* rapidjson 은 위 github 경로 또는 rapidjson 공식 홈페이지에서 받으면 된다.)

2. src/json_parser.cpp

3. sample.cpp

 


소스코드

1. include/json_parser.h

#ifndef __JSON_PARSER_H__
#define __JSON_PARSER_H__

#include <stdarg.h>
#include <string>
#include <vector>

#include "rapidjson/document.h"
#include "rapidjson/pointer.h"
#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/error/en.h"
#include "rapidjson/error/error.h"

using namespace std;
using namespace rapidjson;

class JsonParser {
	private :
		bool	is_debug_print = false;
		void	print_debug_info(const char *_format, ...);
		
		Document t_document;
		
	public :
		JsonParser(bool _is_debug_print = false);
		~JsonParser(void);
		
		void 	set_debug_print(void);

		string  read_file(string _file_path);
		bool	write_file(string _file_path, string _json_string);
		bool	write_json(string _file_path);
		
		bool	parse(const string _data);
		string 	to_string(void);
		
		string 	get_s(string _node_path); // deprecated
		string 	select(string _node_path);
		bool	update(string _node_path, int    _value);
		bool	update(string _node_path, double _value);
		bool	update(string _node_path, string _value);
		bool	add(string _node_path, int    _value);
		bool	add(string _node_path, double _value);
		bool	add(string _node_path, string _value);
		bool	remove(string _node_path);
		
		vector<string>	split(string _string, string _delimiter);
		string 			replace_all(string &_str, const string& _from, const string& _to);
		
};
#endif

 

2. src/json_parser.cpp

#include <stdio.h>
#include <sys/stat.h>

#include <iostream>
#include <sstream>
#include <fstream>

#include "json_parser.h"


JsonParser::JsonParser(bool _is_debug_print) {
	if( this->is_debug_print ) {
		this->set_debug_print();
	}
	this->t_document		= NULL;
	
	this->print_debug_info("JsonParser() create instance\n");
	
	return; 
}

JsonParser::~JsonParser(void) {
	this->print_debug_info("JsonParser() instance destructed\n");
	
	return ;
}

void JsonParser::print_debug_info(const char *_format, ...) {
	if( !this->is_debug_print ) return ;
	
	fprintf(stdout, "JsonParser::");
	va_list arg;
	va_start(arg, _format);
	vprintf(_format, arg);
	va_end(arg);
	
	return ;
}

void JsonParser::set_debug_print(void) {
	this->is_debug_print = true;
	
	this->print_debug_info("set_debug_print() is set on\n");
	
	return ;
}

string JsonParser::read_file(string _file_path) {
	struct stat buffer;   
	if( stat(_file_path.c_str(), &buffer) != 0 ) {
		this->print_debug_info("read_file() not found file path [%s]\n", _file_path.c_str());
		return "";
	}
	  
	ostringstream read_data;
	ifstream fp(_file_path);
	read_data << fp.rdbuf();
	fp.close();
	
	this->print_debug_info("read_file() read from [%s] - [%s]\n", _file_path.c_str(), read_data.str().c_str());
	
	return read_data.str();
}

bool JsonParser::write_file(string _file_path, string _json_string) {
	ofstream out(_file_path);
	
	if( out.is_open() ) {
		out << _json_string;
		out.close();
		
		this->print_debug_info("write_file() write to [%s] - [%s]\n", _file_path.c_str(), _json_string.c_str());
		
		return true;
	
	} else {
		this->print_debug_info("write_file() open failed [%s]\n", _file_path.c_str());
		return false;
	}
}

bool JsonParser::parse(const string _json_string) {
	this->t_document = NULL;
	
	if( _json_string.compare("") == 0 ) {
		this->print_debug_info("parse() JSON parse error : [%02d] %s (offset: %u)\n",
				kParseErrorDocumentEmpty, GetParseError_En(kParseErrorDocumentEmpty), 0);
		
		return false;
	}
	
	ParseResult is_ok = this->t_document.Parse(_json_string.c_str());
	
	if( !is_ok ) {
		this->print_debug_info("parse() JSON parse error : [%02d] %s (offset: %u)\n",
				is_ok.Code(), GetParseError_En(is_ok.Code()), is_ok.Offset());
		
		this->t_document = NULL;
		
		return false;
	}

	this->print_debug_info("parse() convert to json object [%s]\n", _json_string.c_str());
	
	return true;
}

string JsonParser::to_string(void) {
	StringBuffer buffer;
	buffer.Clear();
	
	Writer<StringBuffer> writer(buffer);
	this->t_document.Accept(writer);
	
	string result = buffer.GetString();
	this->print_debug_info("to_string() convert to string [%s]\n", result.c_str());
	
	return result; 
}

// deprecated
string JsonParser::get_s(string _node_path) {
	int   cnt_vector_name;
	bool  is_last_vector = false;
	Value obj_value;
	
	StringBuffer buffer;
	buffer.Clear();
	Writer<StringBuffer> writer(buffer);
			
	vector<string> vector_json_name = this->split(_node_path, "/");
	cnt_vector_name = vector_json_name.size();
	
	Document::AllocatorType& allocator = this->t_document.GetAllocator();
	obj_value.CopyFrom(this->t_document, allocator);
	
	while( !vector_json_name.empty() ) {
		if( --cnt_vector_name == 0 ) {
			is_last_vector = true;
		}
		
		for( Value::ConstMemberIterator itr = obj_value.MemberBegin(); itr != obj_value.MemberEnd() ; ++itr ) {
			if( strcmp(itr->name.GetString(), vector_json_name.front().c_str()) == 0 ) {
				switch( itr->value.GetType() ) {
					case 3 :	// object
						if( !is_last_vector ) {
							obj_value = obj_value[itr->name.GetString()].GetObject();
							break;
						}
						obj_value[itr->name.GetString()].Accept(writer);
						
						return buffer.GetString();
						
					case 4 :	// array
						if( is_last_vector && obj_value[itr->name.GetString()].IsArray() ) {
							// array
							obj_value[itr->name.GetString()].Accept(writer);
							
							return buffer.GetString();
						
						} else {
							vector_json_name.erase(vector_json_name.begin());
							int idx = atoi(vector_json_name.front().c_str());
							if( idx >= (int)obj_value[itr->name.GetString()].Size() ) {
								return "";
							}
							
							if( --cnt_vector_name == 0 ) {
								is_last_vector = true;
							}
							
							if( is_last_vector ) {
								if( obj_value[itr->name.GetString()][idx].IsObject() ) {
									// array
									obj_value = obj_value[itr->name.GetString()][idx].GetObject();
									obj_value.Accept(writer);
																			
								} else {
									// array/index
									obj_value[itr->name.GetString()][idx].Accept(writer);
								}
								
								return buffer.GetString();
							
							} else {
								// array/index/value
								obj_value = obj_value[itr->name.GetString()][idx].GetObject();
							}
						}
						
						break;
						
					case 5 : 	// string
						if( obj_value[itr->name.GetString()].IsString() ) {
							return obj_value[itr->name.GetString()].GetString();
						}
						
						break;
						
					case 0 :	// null
					case 1 :	// false
					case 2 :	// true
					case 6 :	// number
						obj_value[itr->name.GetString()].Accept(writer);
						return buffer.GetString();
						
						break;
				}
				break;
			}
		}
		
		vector_json_name.erase(vector_json_name.begin());
	}
	
	return "";
}

string JsonParser::select(string _node_path) {
	string str_value = "";
	Value *value;

	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		return str_value;
	}

	StringBuffer buffer;
	Writer<StringBuffer> writer(buffer);
	
	value->Accept(writer);
	str_value = buffer.GetString();
	
	// trim begin/end double quotes
	if ( str_value.front() == '"' ) {
		str_value.erase(str_value.begin());
	}

	if( str_value.back() == '"' ) {
		str_value.pop_back();
	}

	return str_value; 
}


bool JsonParser::update(string _node_path, int _value) {
	Value *value;
	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		return false;
	}
	Pointer(_node_path.c_str()).Set(this->t_document, _value);
	
	return true;
}

bool JsonParser::update(string _node_path, double _value) {
	Value *value;
	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		return false;
	}
	Pointer(_node_path.c_str()).Set(this->t_document, _value);
	
	return true;
}

bool JsonParser::update(string _node_path, string _value) {
	Value *value;
	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		return false;
	}
	Pointer(_node_path.c_str()).Set(this->t_document, _value.c_str());
	
	return true;
}

bool JsonParser::add(string _node_path, int _value) {
	Value *value;
	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		Pointer(_node_path.c_str()).Set(this->t_document, _value);
		return true;
	}
	
	return false;
}

bool JsonParser::add(string _node_path, double _value) {
	Value *value;
	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		Pointer(_node_path.c_str()).Set(this->t_document, _value);
		return true;
	}
	
	return false;
}

bool JsonParser::add(string _node_path, string _value) {
	Value *value;
	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		Pointer(_node_path.c_str()).Set(this->t_document, _value.c_str());
		return true;
	}
	
	return false;
}

bool JsonParser::remove(string _node_path) {
	Value *value;
	if( (value = Pointer(_node_path.c_str()).Get(this->t_document)) == 0 ) {
		return false;
	}
	Pointer(_node_path.c_str()).Erase(this->t_document);
	
	return true;
}


bool JsonParser::write_json(string _file_path) {
	StringBuffer buffer;
	PrettyWriter<StringBuffer> writer(buffer);
	
	if( this->t_document.Accept(writer) == false ){ 
		this->print_debug_info("write_json() open failed [%s]\n", _file_path.c_str());
		return false;
	}

	string temp = buffer.GetString();
	ofstream out(_file_path.c_str(),std::ofstream::trunc);
	out << temp;
	
	this->print_debug_info("write_json() write to [%s] - [%s]\n", _file_path.c_str(), temp.c_str());
	
	return true;
}

vector<string> JsonParser::split(string _string, string _delimiter) {
	size_t pos_start = 0, pos_end, delim_len = _delimiter.length();
	string token;
	vector<string> res;

	while ((pos_end = _string.find (_delimiter, pos_start)) != std::string::npos) {
		token = _string.substr (pos_start, pos_end - pos_start);
		pos_start = pos_end + delim_len;
		res.push_back(token);
	}

	res.push_back(_string.substr(pos_start));
	
	return res;
}

string JsonParser::replace_all(string &_str, const string& _from, const string& _to) {
    size_t start_pos = 0;
    
    while( (start_pos = _str.find(_from, start_pos)) != std::string::npos ) {
        _str.replace(start_pos, _from.length(), _to);
        start_pos += _to.length();
    }
    
    return _str;
}

 

3. sample.cpp

#include <stdio.h>
#include <unistd.h>

#include <vector>
#include <iostream>

#include "json_parser.h"

using namespace std;

/* test.json
	{
		"number": { "int": 1, "double": 1.1 },
		"string": "hello world",
		"bool": true,
		"array": [0, 2, 4, 8, 10],
		"null": null,
		"json_array": [{ "int": 2, "double": 2.2 }, { "int": 3, "double": 3.3 }, { "int": 4, "double": 4.4 }]
	}
 
 */

int main(void) {
	// json parser instance 생성
	// instance 생성 시 debug print set 가능
	// args([bool _is_debug_print])
	JsonParser json_parser;
	
	
	// debug print 출력
	json_parser.set_debug_print();
	
	
	// JSON 파일로 부터 JSON string 읽어오기
	// args(<string _file_path>)
	// return - success: string, fail: "" 
	string str_json = json_parser.read_file("./test.json");


	// JSON string 을 JSON document object로 변환
	// args(<string _json_string>)
	// return - true: success, false: failed
	json_parser.parse(str_json);
	
	
	// JSON object로 부터 JSON node value 호출
	// node value 는 단일/하위 path 까지 입력 가능
	// args(<string _node_path>)
	// return - success: string, fail: ""  
	cout << "\n# Parse JSON data" << endl;
	cout << "/number" 				<< "\t\t\t: "	<< json_parser.select("/number") 				<< endl;
	cout << "/number/int"			<< "\t\t: " 	<< json_parser.select("/number/int") 			<< endl;
	cout << "/number/double"		<< "\t\t: " 	<< json_parser.select("/number/double") 		<< endl;
	cout << "/string"				<< "\t\t\t: " 	<< json_parser.select("/string") 				<< endl;
	cout << "/bool"					<< "\t\t\t: " 	<< json_parser.select("/bool")	 				<< endl;
	cout << "/array"				<< "\t\t\t: " 	<< json_parser.select("/array")	 				<< endl;
	cout << "/array/0"				<< "\t\t: " 	<< json_parser.select("/array/0") 				<< endl;
	cout << "/array/1"				<< "\t\t: " 	<< json_parser.select("/array/1") 				<< endl;
	cout << "/array/2"				<< "\t\t: " 	<< json_parser.select("/array/2") 				<< endl;
	cout << "/array/3"				<< "\t\t: " 	<< json_parser.select("/array/3") 				<< endl;
	cout << "/array/4"				<< "\t\t: " 	<< json_parser.select("/array/4") 				<< endl;
	cout << "/null"					<< "\t\t\t: " 	<< json_parser.select("/null")	 				<< endl;
	cout << "/json_array"			<< "\t\t: " 	<< json_parser.select("/json_array")			<< endl;
	cout << "/json_array/0"			<< "\t\t: " 	<< json_parser.select("/json_array/0")			<< endl;
	cout << "/json_array/0/int"		<< "\t: " 		<< json_parser.select("/json_array/0/int")		<< endl;
	cout << "/json_array/0/double"	<< "\t: " 		<< json_parser.select("/json_array/0/double")	<< endl;
	cout << "/json_array/1"			<< "\t\t: " 	<< json_parser.select("/json_array/1")			<< endl;
	cout << "/json_array/1/int"		<< "\t: " 		<< json_parser.select("/json_array/1/int")		<< endl;
	cout << "/json_array/1/double"	<< "\t: " 		<< json_parser.select("/json_array/1/double")	<< endl;
	cout << "/json_array/2"			<< "\t\t: " 	<< json_parser.select("/json_array/2")			<< endl;
	cout << "/json_array/2/int"		<< "\t: " 		<< json_parser.select("/json_array/2/int")		<< endl;
	cout << "/json_array/2/double"	<< "\t: " 		<< json_parser.select("/json_array/2/double")	<< endl;
	cout << "/json_array/2/none"	<< "\t: " 		<< json_parser.select("/json_array/2/none")	<< endl;
	
	
	printf("\n# casting data type\n");
	// parse 된 모든 결과물은 string이기 때문에 데이터 타입에 맞게 casting 하여 사용
	int    num_int_value    = stoi(json_parser.select("/number/int"));
	double num_double_value = stod(json_parser.select("/number/double"));
	printf(" - int[%d] double[%lf] \n", num_int_value, num_double_value);
	
	
	printf("\n# split: vector<string> array\n");
	// string에서 지정한 delimiter로 분할하여 vector<string> array 로 생성
	// return - vector array
	vector<string> v_arr_values = json_parser.split("1,3,5,7,9", ",");
	for( int idx = 0 ; idx < v_arr_values.size() ; idx++ ) {
		printf(" - v_arr_values[%d] = %d\n", idx, stoi(v_arr_values.at(idx)));
	}
	
	printf("\n# JSON object to string\n");
	// instance에 저장된 JSON object를 string으로 변환
	// return - success: string, fail: "" 
	string to_string = json_parser.to_string();
	
	
	printf("\n# replace string\n");
	// string에서 해당하는 문자열을 모두 치환
	// args(<string _string, string _from, string _to>)
	// return - true: success, false: failed
	json_parser.replace_all(to_string, "hello world", "new world");
	printf(" -[%s]\n", to_string.c_str());

	
	printf("\n# write file\n");
	// json string을 file에 저장, pretty-printing 적용 안됨
	// args(<string _file_path, string _json_string>)
	// return - true: success, false: failed
	json_parser.write_file("test2.json", to_string);
	
	
	printf("\n# update json data\n");
	json_parser.update("/number/int",  5);
	json_parser.update("/number/test", 5);

	to_string = json_parser.to_string();
	printf(" -[%s]\n", to_string.c_str());
		
	
	printf("\n# add json data\n");
	json_parser.add("/number/int",  6);
	json_parser.add("/number/test", 6);
	
	to_string = json_parser.to_string();
	printf(" -[%s]\n", to_string.c_str());
	
	printf("\n# remove json data\n");
	json_parser.remove("/number/test");
	
	to_string = json_parser.to_string();
	printf(" -[%s]\n", to_string.c_str());
	
	printf("\n# write json data with pretty printing\n");
	json_parser.write_json("./test3.json");
	
	
	return 0;
}

 

* 예제파일 : test.json

{
	"number": { "int": -1, "double": 1.1 },
	"string": "hello world",
	"bool": true,
	"array": [0, 2, 4, 8, 10],
	"null": null,
	"json_array": [{ "int": 2, "double": 2.2 }, { "int": 3, "double": 3.3 }, { "int": 4, "double": 4.4 }]
}

 

 

컴파일 및 실행 결과

- 라이브러리 빌드, 샘플의 컴파일, LD_LIBRARY_PATH 환경설정 그리고 실행의 과정과 결과이다.

자세한 설명은 위 소스코드 내에 모두 들어있으니 참고 바란다.

muabow@muabow-WorkSpace:~/github/library/cpp/lib_json_parser$ make clean ; make
rm -Rf  ./src/json_parser.o libjson_parser.so
g++  -fPIC -I./include -c src/json_parser.cpp -o src/json_parser.o --std=c++11
g++ -shared -o libjson_parser.so  ./src/json_parser.o
muabow@muabow-WorkSpace:~/github/library/cpp/lib_json_parser$ g++ -o sample sample.cpp -I./include -L./ -ljson_parser -std=c++11
muabow@muabow-WorkSpace:~/github/library/cpp/lib_json_parser$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)
muabow@muabow-WorkSpace:~/github/library/cpp/lib_json_parser$
muabow@muabow-WorkSpace:~/github/library/cpp/lib_json_parser$ ./sample
JsonParser::set_debug_print() is set on
JsonParser::read_file() read from [./test.json] - [{
        "number": { "int": -1, "double": 1.1 },
        "string": "hello world",
        "bool": true,
        "array": [0, 2, 4, 8, 10],
        "null": null,
        "json_array": [{ "int": 2, "double": 2.2 }, { "int": 3, "double": 3.3 }, { "int": 4, "double": 4.4 }]
}
]
JsonParser::parse() convert to json object [{
        "number": { "int": -1, "double": 1.1 },
        "string": "hello world",
        "bool": true,
        "array": [0, 2, 4, 8, 10],
        "null": null,
        "json_array": [{ "int": 2, "double": 2.2 }, { "int": 3, "double": 3.3 }, { "int": 4, "double": 4.4 }]
}
]

# Parse JSON data
/number                 : {"int":-1,"double":1.1}
/number/int             : -1
/number/double          : 1.1
/string                 : hello world
/bool                   : true
/array                  : [0,2,4,8,10]
/array/0                : 0
/array/1                : 2
/array/2                : 4
/array/3                : 8
/array/4                : 10
/null                   : null
/json_array             : [{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]
/json_array/0           : {"int":2,"double":2.2}
/json_array/0/int       : 2
/json_array/0/double    : 2.2
/json_array/1           : {"int":3,"double":3.3}
/json_array/1/int       : 3
/json_array/1/double    : 3.3
/json_array/2           : {"int":4,"double":4.4}
/json_array/2/int       : 4
/json_array/2/double    : 4.4
/json_array/2/none      :

# casting data type
 - int[-1] double[1.100000]

# split: vector<string> array
 - v_arr_values[0] = 1
 - v_arr_values[1] = 3
 - v_arr_values[2] = 5
 - v_arr_values[3] = 7
 - v_arr_values[4] = 9

# JSON object to string
JsonParser::to_string() convert to string [{"number":{"int":-1,"double":1.1},"string":"hello world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]

# replace string
 -[{"number":{"int":-1,"double":1.1},"string":"new world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]

# write file
JsonParser::write_file() write to [test2.json] - [{"number":{"int":-1,"double":1.1},"string":"new world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]

# update json data
JsonParser::to_string() convert to string [{"number":{"int":5,"double":1.1},"string":"hello world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]
 -[{"number":{"int":5,"double":1.1},"string":"hello world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]

# add json data
JsonParser::to_string() convert to string [{"number":{"int":5,"double":1.1,"test":6},"string":"hello world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]
 -[{"number":{"int":5,"double":1.1,"test":6},"string":"hello world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]

# remove json data
JsonParser::to_string() convert to string [{"number":{"int":5,"double":1.1},"string":"hello world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]
 -[{"number":{"int":5,"double":1.1},"string":"hello world","bool":true,"array":[0,2,4,8,10],"null":null,"json_array":[{"int":2,"double":2.2},{"int":3,"double":3.3},{"int":4,"double":4.4}]}]

# write json data with pretty printing
JsonParser::write_json() write to [./test3.json] - [{
    "number": {
        "int": 5,
        "double": 1.1
    },
    "string": "hello world",
    "bool": true,
    "array": [
        0,
        2,
        4,
        8,
        10
    ],
    "null": null,
    "json_array": [
        {
            "int": 2,
            "double": 2.2
        },
        {
            "int": 3,
            "double": 3.3
        },
        {
            "int": 4,
            "double": 4.4
        }
    ]
}]
JsonParser::JsonParser() instance destructed

 

개인적으로 제일 자주 사용하는 라이브러리이다. 아무래도 JSON format을 사용 하는 곳이 많다보니..

C/C++에서는 string parse가 무척 귀찮고 어려운 경우가 많아서 그렇지 string이든 JSON이든 패턴만 잘 잡아두면 두고두고 유용하다.

 

끝.

 

 

댓글