카테고리 없음
Json
denny
2025. 5. 26. 11:34
- 빠르고 가벼운 JSON 파서: RapidJSON
- JSON Schema 기반 C++ 코드 자동 생성: Python + Jinja2
으로 전체 구조와 예제를 제공하겠습니다.
✅ 목표
- RapidJSON만 사용하여 가볍고 빠른 JSON 파싱
- JSON Schema 기반 Python 코드 생성기로 C++ 구조체 자동 생성
- from_json() / to_json() 대신 RapidJSON의 DOM API 사용
🧩 1. JSON Schema 예시
📁 schema/character.schema.json
{
"title": "Character",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"hp": { "type": "integer" },
"class": {
"type": "string",
"enum": ["Warrior", "Mage", "Archer"]
}
},
"required": ["id", "name", "hp", "class"]
}
🛠️ 2. Python + Jinja2: 구조체 생성기
📁 template/class.hpp.jinja2
#pragma once
#include <string>
#include <rapidjson/document.h>
enum class {{ enum_name }} {
{% for val in enum_values %}
{{ val }}{{ "," if not loop.last }}
{% endfor %}
};
struct {{ struct_name }} {
int id;
std::string name;
int hp;
{{ enum_name }} class_type;
// RapidJSON을 이용한 역직렬화
static {{ struct_name }} FromJSON(const rapidjson::Value& obj) {
{{ struct_name }} c;
c.id = obj["id"].GetInt();
c.name = obj["name"].GetString();
c.hp = obj["hp"].GetInt();
std::string cls = obj["class"].GetString();
if (cls == "Warrior") c.class_type = {{ enum_name }}::Warrior;
else if (cls == "Mage") c.class_type = {{ enum_name }}::Mage;
else if (cls == "Archer") c.class_type = {{ enum_name }}::Archer;
return c;
}
};
📁 codegen.py
import json
import jinja2
def main():
with open("schema/character.schema.json") as f:
schema = json.load(f)
struct_name = schema["title"]
enum_name = "CharacterClass"
enum_values = schema["properties"]["class"]["enum"]
env = jinja2.Environment(loader=jinja2.FileSystemLoader("template"))
tmpl = env.get_template("class.hpp.jinja2")
output = tmpl.render(
struct_name=struct_name,
enum_name=enum_name,
enum_values=enum_values
)
with open("output/character.hpp", "w") as f:
f.write(output)
if __name__ == "__main__":
main()
🧪 3. 예제 main.cpp
📁 main.cpp
#include <iostream>
#include <rapidjson/document.h>
#include <fstream>
#include <sstream>
#include "character.hpp"
int main() {
std::ifstream in("data.json");
std::stringstream ss;
ss << in.rdbuf();
std::string json_str = ss.str();
rapidjson::Document doc;
doc.Parse(json_str.c_str());
if (!doc.IsObject()) {
std::cerr << "Invalid JSON\n";
return 1;
}
Character c = Character::FromJSON(doc);
std::cout << "ID: " << c.id << ", Name: " << c.name << ", HP: " << c.hp << "\n";
}
📄 예제 JSON 입력 (data.json)
{
"id": 1001,
"name": "Auron",
"hp": 180,
"class": "Warrior"
}
⚙️ CMake 설정
📁 CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MMORPG_RapidJSON)
set(CMAKE_CXX_STANDARD 17)
include_directories(${CMAKE_SOURCE_DIR}/external/rapidjson/include)
add_executable(server main.cpp output/character.hpp)
external/rapidjson/include는 RapidJSON을 clone한 경로입니다.
📌 요약
항목 사용 도구 설명
JSON 파서 | RapidJSON | 매우 빠르고 가벼움, MMORPG 서버에 적합 |
코드 생성 | Python + Jinja2 | JSON Schema → 구조체 자동 생성 |
enum / struct 변환 | 직접 구현 | RapidJSON DOM 기반 구조 파싱 지원 |