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
}
}
}