C構造体からJSONへのシリアライズ、デシリアライズコードを自動生成する方法

JSON形式でデータを交換したいが、特に構造体がネストしている場合、生成と解析のコードを手動で記述するのは面倒です。このプロセスを自動化する方法を紹介します。

独自の構造を定義し、Pythonでその構造を解析し、Cheetahライブラリを使用して変換コードを生成します。 再帰的なアプローチを使用して構造体のネストを処理し、コード量を削減します。

依存関係のインストール

pip install dicttoxml
pip install Cheetah3
# JsonSerialization.tar.gzをダウンロード
tar -xf JsonSerialization

構造の定義 (JsonSerialization/codegen/metrics.ini)

struct AccuracyStruct
{
    LTDouble acc;
};

struct HostLatencyStruct
{
    LTDouble e2e;
};

struct MetricItemStruct
{
    LTString       Version;          
    LTDouble       Util;
    AccuracyStruct Accuracy;
    HostLatencyStruct HostLatency;
};

struct ShapeInfoStruct
{
    LTString shape;
};

struct ModelInfoStruct
{
    LTInteger StackSize;
    LTInteger LocalMemSize;
    LIST<ShapeInfoStruct> input_shape;
    LIST<ShapeInfoStruct> output_shape;
};

struct Metrics
{      
    LTString         Name;      
    ModelInfoStruct  Info;
    MetricItemStruct version;
};

テストDEMO (JsonSerialization/main.cpp)

#include <fstream>
#include <iostream>
#include <cassert>
#include <cmath>
#include <numeric>
#include <string> 
#include <string.h> 
#include <sstream> 
#include <cassert>
#include "auto_json.h"

using namespace std;

int main()
{
    auto saveConfiguration = [](ConfigurationData configData, const char * filepath) {
                string strContent;
                configData.Save(strContent);
                std::ofstream outFile;
                outFile.open(filepath);
                outFile << strContent;
                outFile.close();         
         };
         
    auto loadConfiguration = [](ConfigurationData &configData, const char * filepath)->bool {
            std::ifstream in(filepath);
            if (in.is_open())
            {
                std::stringstream buffer;
                buffer << in.rdbuf();
                std::string contents(buffer.str());
                configData.Load(contents.c_str());
                in.close();
                return true;
            }
            in.close();
            return false;
         };
    // 生成
    const char * filepath="config.json";
    ConfigurationData configData;
    configData.applicationName="Hello";
    configData.modelSpecification.stackSize=48;
    configData.modelSpecification.localMemSize=50;
    ShapeInfoStruct inshape;
    inshape.shape="1,3,224,224";
    configData.modelSpecification.inputShape.push_back(inshape);

    ShapeInfoStruct oshape;
    oshape.shape="1,100";
    configData.modelSpecification.outputShape.push_back(oshape);

    configData.metricData.accuracy.acc=0.5;
    configData.metricData.hostLatency.e2e=300;
    configData.metricData.version="v2.0";
    configData.metricData.util=0.9;
    
    // 保存
    saveConfiguration(configData, filepath);
   
    // 読み込み
    ConfigurationData loadedConfig;
    assert(loadConfiguration(loadedConfig, filepath));
    
    // 変更
    loadedConfig.metricData.accuracy.acc=0.6;
    
    // 再度保存
    saveConfiguration(loadedConfig, filepath);
    return 0;
}

コンパイルと実行

cd JsonSerialization
cd codegen/
python codegen.py metrics.ini
cd ..
make
./demo
cat config.json

出力結果

{
        "applicationName": "Hello",
        "modelSpecification": {
                "stackSize":    48,
                "localMemSize": 50,
                "inputShape":   [{
                                "shape":        "1,3,224,224"
                        }],
                "outputShape":  [{
                                "shape":        "1,100"
                        }]
        },
        "metricData":     {
                "version":      "v2.0",
                "util": 0.9,
                "accuracy":     {
                        "acc":  0.6
                },
                "hostLatency":  {
                        "e2e":  300
                }
        }
}

タグ: C言語 JSON シリアライズ コード生成 Python

7月19日 02:21 投稿