ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Json
    카테고리 없음 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 기반 구조 파싱 지원

     

Designed by Tistory.