2017年6月7日 Theolizer®最新版v1.1.0へ対応するために修正しました。
最新版のソース一式をGistに置いてます。

こんにちは。田原です。

プログラムの開発中に構造体やクラス、enum型の定義変更は日常茶飯事ですね。そして、古いプログラムで保存したファイルを新しいプログラムで読む必要があります。Theolizer®ではこれらに2種類の方法を組み合わせて対処します。前回、定義変更方法について解説しました。今回はバージョン・アップ/ダウン処理について解説します。

1.どんな特に使うのか

前回の方法でクラスや構造体のメンバ変数定義を変更できます。そして、それでは足りずバージョン・アップ処理を書く必要がでてきたら、今回の方法で対応します。また、旧バージョンのデータを保存したいプログラムもあると思います。その時、バージョン・ダウン処理を追加します。

この方法は他に2つの場面でも使えます。

  1. クラスや構造体のメンバ変数名を変更する時
  2. enum型のシンボル名を重複して変更する時
    一度使ったシンボル名を再度使いたい場合は、バージョン・アップすることで使えるようになります。

1-1.バージョン番号について

バージョン・アップ/ダウン処理を書く時、どのバージョンに対するアップ/ダウン処理なのか指定する必要がありますので、バージョン番号を定義します。1から初めて1組のバージョン・アップ/ダウン処理を書く度に1つ上げます。

そして、例えば、最新版がバージョン5でバージョン3のファイルから回復したいような時、Theolizer®は自動的にバージョン3→バージョン4→バージョン5とカスケードにバージョン・アップ処理を行います。
バージョン・ダウンの時も同様です。最新版のバージョンが5のプログラムがバージョン3のファイルを保存する時、Theolizer®は自動的にバージョン5→バージョン4→バージョン3とカスケードにバージョン・ダウン処理を行い、目標バージョンのファイルを保存します。

従来のシリアライザはこのような時には、過去の全てのバージョンから最新版への変換処理を記述する必要がありましたので、バージョンが上がってくるとメンテナンスが大変でした。
Theolizer®はバージョンを1つ上げる時にバージョン・アップ処理を1つ追加するだけでOKです。古いバージョン・アップ処理に手を入れる必要がありません。

1-2.グローバル・バージョン番号テーブルについて

1つのアプリケーションは複数のクラスを持ちますし、全てのクラスが一斉にバージョン・アップすることはありません。従って、各クラスのバージョンはまちまちとなります。
ですので、旧バージョンで保存する際、各クラスのバージョンを1つ1つ指定するコードを書くのは現実的ではありません。

そこで、グローバルなバージョン番号を定義し、その番号と各クラスのバージョンの対応表を自動生成するようにしました。これをグローバル・バージョン番号テーブルと呼んでます。

また、このグローバル・バージョン番号テーブルを回復処理でも用いることで、シリアライズ・データ内に各クラスや構造体のバーション番号を1つ1つ記録しないで済むようにしています。(今までのサンプルが出力した各jsonファイルの先頭付近の“GlobalVersionNo”:1がこのグローバル・バージョン番号です。)

2.バージョン番号管理を行う時の手順

今回はいつもの家計簿サンプル・ソースを変更しますが、その前にバージョン管理の手順を説明します。

2-1.手順1(バージョン管理開始時に一度だけ行う。)

3回目の技術ブログで下記を仕込みました。バージョン番号による管理を始める時、まず最初にこれら2つを定義します。

  1. #define THEOLIZER_GLOBAL_VERSION_TABLE
    グローバル・バージョン番号テーブルの実体はアプリケーション全体で1つです。その実体を生成するコンパイル単位(cppファイル)にてTHEOLIZER_GLOBAL_VERSION_TABLEを定義します。

  2. THEOLIZER_DEFINE_GLOBAL_VERSION_TABLE(GlobalVersionTable, 1);
    全てのバージョン指定を行うクラス・構造体・enum型の定義より前でTHEOLIZER_DEFINE_GLOBAL_VERSION_TABLE()マクロを設置し、現在のグローバル・バージョン番号を指定します。
    グローバル・バージョン番号は必ず1から始めて下さい。そして、この時の各クラス・構造体・enum型のバーションがグローバル・バージョン番号1に対応するバージョンとなります。なお、バージョン番号を指定していないもののバージョンは自動的に1となります。

次に、プロジェクトをビルドし、Theolizer®でソース自動生成を行います。
そして、生成されたソースをgitやsvn等お使いのバージョン管理システムへ登録します。
自動生成ソースにはその時までの各バージョンのクラス・構造体・enum型の定義情報、および、グローバル・バージョン番号テーブルが含まれています。そのため、バージョン管理システムの管理対象としておかないと、情報に矛盾が発生する可能性があるのです。

2-2.手順2(バージョン・アップ/ダウン処理を追加する度に行う。)

グローバル・バージョン番号と、バージョン番号を変更するクラス・構造体・enum型、および、それらを含むクラス・構造体(*1)のバージョンを1つ増やします。

(*1)クラス・構造体・enum型を直接含むクラスや構造体とは
基底クラスやメンバ変数としてクラス・構造体・enum型を持つ場合が該当します。
それらへのポインタの場合は「直接」ではないので該当しません。

そして、バージョン・アップ/ダウン関数を該当のクラス内に記述し、ビルドします。

バージョン・アップ/ダウン関数を記述するには、下記のような雛形を対象のクラス・構造体定義の直後にコピーし、雛形の「対象クラス」を対象のクラス・構造体名を変更、雛形の「バージョン番号」はバージョンアップ直前のバージョン番号を記載します。例えば、バージョン3を作った時はバージョン番号を2とします。

template<class tTheolizerVersion, class tNextVersion>
struct 対象クラス::TheolizerUserDefine<tTheolizerVersion, tNextVersion, バージョン番号>
{
    // Members version down.
    static void downVersion(tNextVersion const& iNextVersion, tTheolizerVersion& oNowVersion)
    {
        // バージョン・ダウン処理を記述する。
    }
    // Members version up.
    static void upVersion(tTheolizerVersion const& iNowVersion, tNextVersion& oNextVersion)
    {
        // バージョン・アップ処理を記述する。
    }
};

3.家計簿サンプルのバージョン・アップ

今回は一部の科目について在庫数量を管理できるようにします。

  1. Item構造体の変更
    バージョン1ではbool mDoManage;で残高管理するかどうかだけ設定していました。それをManageType mManageType;とし、管理しない(emtNone)、残高管理する(emtMoney)、在庫管理する(emtCount)へ変更します。型も異なり値の割り当て方も変わるため、バージョン・アップ処理が必要になります。また、ついでに数え方(単位mUnit)も追加しました。

  2. Trade構造体の変更
    バージョン1では取引高としてmAmount(円)だけでした。それを借方(mDebitAmount)、貸方(mCreditAmount)の2つに拡張しました。
    在庫管理する時は増減する数を記載します。例えばパンを6枚158円で購入した時は、mDebitAmount=6、mCreditAmount=158となります。Itemと同じくバージョン・アップ処理が必要になります。

ついでにバージョン・ダウンもできるようにしてみました。

4.今回のソース・コード

前節で記載した変更点は全てここで記述します。バージョン・アップ/ダウン関数は、下記構造体にdownVersion()関数、upVersion()関数として定義します。

4-1.バージョン2構造体定義

common.h
[cpp] //############################################################################
// Theolizer解説用サンプル・プログラム4
//
// 簡単な家計簿用共通定義
//############################################################################

#if !defined(COMMON_H)
#define COMMON_H

// ***************************************************************************
// インクルード
// ***************************************************************************

// 標準ライブラリ
#include <string>

// Theolizerライブラリ
#include <theolizer/serializer_json.h>
#include <theolizer/list.h>

// ***************************************************************************
// 保存先定義
// ***************************************************************************

THEOLIZER_DESTINATIONS
(
All, // 引き継ぎ元保存先定義の最後のシンボル
Settings, // 設定情報
Data // データ
);

#define SETTINGS THEOLIZER_ANNOTATE(FS:<theolizerD::Settings>)
#define DATA THEOLIZER_ANNOTATE(FS:<theolizerD::Data>)
#define NO_SAVE THEOLIZER_ANNOTATE(FN)

// ***************************************************************************
// グローバル・バージョン番号テーブル
// ***************************************************************************

THEOLIZER_DEFINE_GLOBAL_VERSION_TABLE(GlobalVersionTable, 2);

// ***************************************************************************
// 構造体定義
// ***************************************************************************

#define POINTEE THEOLIZER_ANNOTATE(FS:<>Pointee)

//—————————————————————————-
// 科目管理
//—————————————————————————-

// 管理種別
enum ManageType
{
emtNone, // 在庫管理無し
emtMoney, // 金額管理
emtCount // 数量管理
};

// 科目
struct Item
{
Item* mParent SETTINGS; // 親科目
std::string mName SETTINGS; // 科目名
bool mIsAssets SETTINGS; // 資産(財布や預金)
int mAssetsIncrease NO_SAVE; // 増加した資産金額(保存無し)
ManageType mManageType SETTINGS; // 管理種別
int mAmount DATA; // 残高
std::string mUnit SETTINGS; // 単位
theolizer::ListPointee<Item> mChildren; // 子科目

Item()
{
mParent=NULL;
mManageType=emtNone;
}

THEOLIZER_INTRUSIVE(CS, (Item), 2);
};

typedef theolizer::ListPointee<Item>::iterator ChildIterator;

// バージョン・アップ/ダウン処理
template<class tTheolizerVersion, class tNextVersion>
struct Item::TheolizerUserDefine<tTheolizerVersion, tNextVersion, 1>
{
// Initialize members that is deleted in next version.
static void initialize(tTheolizerVersion& oNowVersion)
{
oNowVersion.mDoManage=false;
}

// Members version down.
static void downVersion(tNextVersion const& iNextVersion, tTheolizerVersion& oNowVersion)
{
if (iNextVersion.mManageType == emtMoney)
{
oNowVersion.mDoManage=true;
}
else
{
oNowVersion.mDoManage=false;
oNowVersion.mAmount=0;
}
}

// Members version up.
static void upVersion(tTheolizerVersion const& iNowVersion, tNextVersion& oNextVersion)
{
if (iNowVersion.mDoManage)
{
oNextVersion.mManageType.set(emtMoney, iNowVersion.mDoManage.getDoSucceed());
}
else
{
oNextVersion.mManageType.set(emtNone, iNowVersion.mDoManage.getDoSucceed());
}
}
};

//—————————————————————————-
// 取引記録
//—————————————————————————-

struct Date
{
short mYear; // 年
char mMonth; // 月(1-12)
char mDay; // 日(1-31)
};

struct Trade
{
Date mDate; // 取引日
Item* mDebitItem; // 購入品(借方科目)
int mDebitAmount; // 借方数量
int mCreditAmount; // 貸方数量
Item* mCreditItem; // 財布 (貸方科目)
std::string mNote; // 備考

THEOLIZER_INTRUSIVE(CS, (Trade), 2);
};

// バージョン・アップ/ダウン処理
template<class tTheolizerVersion, class tNextVersion>
struct Trade::TheolizerUserDefine<tTheolizerVersion, tNextVersion, 1>
{
// Initialize members that is deleted in next version.
static void initialize(tTheolizerVersion& oNowVersion)
{
oNowVersion.mAmount=0;
}

// Members version down.
static void downVersion(tNextVersion const& iNextVersion, tTheolizerVersion& oNowVersion)
{
// 新データへ読み込む時(デフォルト・コンストラクタで生成されている)に呼ばれるので対応
if ((!iNextVersion.mDebitItem) || (!iNextVersion.mCreditItem))
return;

int aMoney=0;
if (iNextVersion.mDebitItem->mManageType == emtMoney)
{
aMoney=iNextVersion.mDebitAmount;
}
else if (iNextVersion.mCreditItem->mManageType == emtMoney)
{
aMoney=iNextVersion.mCreditAmount;
}
else if ((iNextVersion.mDebitItem->mManageType != emtCount)
&& (iNextVersion.mCreditItem->mManageType != emtCount))
{
aMoney=iNextVersion.mDebitAmount;
}
oNowVersion.mAmount=aMoney;
}

// Members version up.
static void upVersion(tTheolizerVersion const& iNowVersion, tNextVersion& oNextVersion)
{
// 回復順序によっては未設定なので対応
if ((!oNextVersion.mDebitItem) || (!oNextVersion.mCreditItem))
return;

if (oNextVersion.mDebitItem->mManageType != emtCount)
{
oNextVersion.mDebitAmount.set(iNowVersion.mAmount,iNowVersion.mAmount.getDoSucceed());
}
if (oNextVersion.mCreditItem->mManageType != emtCount)
{
oNextVersion.mCreditAmount.set(iNowVersion.mAmount,iNowVersion.mAmount.getDoSucceed());
}
}
};

//—————————————————————————-
// 家計簿
//—————————————————————————-

struct HouseholdAccounts
{
Item mItemTree POINTEE; // 科目ツリー
std::list<Trade> mTradeList DATA; // 取引のリスト

THEOLIZER_INTRUSIVE(CS, (HouseholdAccounts), 2);
};

typedef std::list<Trade>::iterator TradeIterator;

// ***************************************************************************
// 関数群
// ***************************************************************************

//—————————————————————————-
// 初期設定
//—————————————————————————-

void initialize(HouseholdAccounts* oHouseholdAccounts);
void display( HouseholdAccounts* iHouseholdAccounts);
void calculate( HouseholdAccounts* ioHouseholdAccounts);

#endif
[/cpp]

バージョン1形式での保存とバージョン1形式からの回復をデモできるようにするため、コマンド・ライン引き数で1を指定するとバージョン1を保存し、Lを指定すると保存を行わずにSettings.jsonとData.jsonから回復すようにしています。

4-2.データの保存と回復、および、簡単な集計と表示

main.cpp
[cpp] //############################################################################
// Theolizer解説用サンプル・プログラム4
//
// メイン処理(データ保存/回復サンプル)
//############################################################################

#define THEOLIZER_GLOBAL_VERSION_TABLE

// ***************************************************************************
// インクルード
// ***************************************************************************

// 標準ライブラリ
#include <iostream>
#include <fstream>
#include <cstdlib>

// 共通定義
#include "common.h"

// Theolizer自動生成先
#include "main.cpp.theolizer.hpp"

// ***************************************************************************
// メイン
// ***************************************************************************

int main(int argc, char* argv[])
{
//—————————————————————————-
// バラメータ解析
//—————————————————————————-

unsigned aGlobalVersionNo=theolizer::kLastGlobalVersionNo;
bool aLoadOnly=false;
if (1 < argc)
{
unsigned temp=(unsigned)(strtoul(argv[1], nullptr, 10));
if (temp && (temp < aGlobalVersionNo))
{
aGlobalVersionNo=temp;
}

std::string argv1=argv[1];
if ((argv1 == "l") || (argv1 == "L"))
{
aLoadOnly=true;
}
}

std::string aSettings;
std::string aData;
if (aLoadOnly)
{
aSettings = "Settings.json";
aData = "Data.json";
std::cout << theolizer::print("LoadOnly:%d\n", aLoadOnly);
}
else
{
aSettings = theolizer::print("Settings%d.json", aGlobalVersionNo).str();
aData = theolizer::print("Data%d.json", aGlobalVersionNo).str();
std::cout << theolizer::print("GlobalVersionNo=%d LoadOnly:%d\n",
aGlobalVersionNo, aLoadOnly);
}

std::cout << theolizer::print("Files : %s, %s\n", aSettings, aData);

//—————————————————————————-
// 家計簿設定
//—————————————————————————-

if (!aLoadOnly)
{
// 保存用家計簿
HouseholdAccounts aHouseholdAccountsSave;

// 初期設定(科目と取引データを設定している)
initialize(&aHouseholdAccountsSave);

//—————————————————————————-
// 保存
//—————————————————————————-

std::cout << u8"<<< 保存するサンプル・データ >>>\n";
display(&aHouseholdAccountsSave);

// 保存処理(Settings)
{
// 保存先のファイルをオープンする
std::ofstream aStream(aSettings);

// シリアライザを用意する
theolizer::JsonOSerializer<theolizerD::Settings> js(aStream, aGlobalVersionNo);

// 家計簿をSettings.jsonファイルへ保存する
THEOLIZER_PROCESS(js, aHouseholdAccountsSave);

// オブジェクト追跡の締め
js.clearTracking();
}

// 保存処理(Data)
{
// 保存先のファイルをオープンする
std::ofstream aStream(aData);

// シリアライザを用意する
theolizer::JsonOSerializer<theolizerD::Data> js(aStream, aGlobalVersionNo);

// 家計簿をData.jsonファイルへ保存する
THEOLIZER_PROCESS(js, aHouseholdAccountsSave);

// オブジェクト追跡の締め
js.clearTracking();
}
}

//—————————————————————————-
// 回復
//—————————————————————————-

// 回復用家計簿(正確に回復できていることを示すため、保存用と別領域)
HouseholdAccounts aHouseholdAccountsLoad;

// 回復処理(Settings)
{
// 回復元のファイルをオープンする
std::ifstream aStream(aSettings);

// シリアライザを用意する
theolizer::JsonISerializer<theolizerD::Settings> js(aStream);

// 家計簿をSettings.jsonファイルから回復する
THEOLIZER_PROCESS(js, aHouseholdAccountsLoad);

// オブジェクト追跡の締め
js.clearTracking();
}

// 回復処理(Data)
{
// 回復元のファイルをオープンする
std::ifstream aStream(aData);

// シリアライザを用意する
theolizer::JsonISerializer<theolizerD::Data> js(aStream);

// 家計簿をData.jsonファイルから回復する
THEOLIZER_PROCESS(js, aHouseholdAccountsLoad);

// オブジェクト追跡の締め
js.clearTracking();
}

//—————————————————————————-
// 内容表示と簡単な集計処理
//—————————————————————————-

std::cout << u8"\n\n<<< 回復したサンプル・データ >>>\n";
display(&aHouseholdAccountsLoad);

std::cout << u8"\n\n<<< サンプルの集計結果 >>>\n";
calculate(&aHouseholdAccountsLoad);

return 0;
}
[/cpp]

新しく追加した機能に対応しています。また、在庫が減ることもデモに含めるため、科目定義に「消費」を追加してます。

4-3.家計簿アプリケーションのメインに当たる部分

sub.cpp
[cpp] //############################################################################
// Theolizer解説用サンプル・プログラム4
//
// 補助関数群(家計簿にサンプル・データ設定/表示)
//############################################################################

#define THEOLIZER_NO_ANALYZE

// ***************************************************************************
// インクルード
// ***************************************************************************

// 標準ライブラリ
#include <iostream>
#include <fstream>

// 共通定義
#include "common.h"

// ***************************************************************************
// 家計簿にサンプル・データ設定
// ***************************************************************************

//—————————————————————————-
// find 科目
//—————————————————————————-

Item* find(Item* iItem, char const* iItemName)
{
if (iItem->mName == iItemName)
return iItem;

for (ChildIterator itr=iItem->mChildren.begin(); itr != iItem->mChildren.end(); ++itr)
{
Item* ret=find(&(*itr), iItemName);
if (ret)
return ret;
}

return NULL;
}

//—————————————————————————-
// 科目ツリー設定
// 家計
// 収入
// 給料
// 雑収入
// 支出
// 食費
// 主食
// お米 在庫管理(g)
// パン 在庫管理(枚)
// 副食
// 肉魚 在庫管理(g)
// 野菜 在庫管理(g)
// 果物
// 現金
// 財布 残高管理
// 預金 残高管理
// 消費
// 利用
// 廃棄
//—————————————————————————-

// —<<< 子科目設定 >>>—

Item* pushItem
(
Item* oItem,
char const* iItemName,
std::string iUnit="",
bool iIsAssets=false,
ManageType iManageType=emtNone,
int iAmount=0
)
{
Item aItem;
aItem.mParent =oItem;
aItem.mName =iItemName;
aItem.mUnit =iUnit;
aItem.mIsAssets =iIsAssets;
aItem.mAssetsIncrease =0;
aItem.mManageType =iManageType;
aItem.mAmount =iAmount;

oItem->mChildren.push_back(aItem);
return &(oItem->mChildren.back());
}

// —<<< 科目ツリー設定 >>>—

void makeItems(Item* oItemTree)
{
oItemTree->mParent =NULL;
oItemTree->mName =u8"家計";
oItemTree->mIsAssets =false;
oItemTree->mManageType =emtNone;
oItemTree->mAmount =0;
oItemTree->mUnit ="";

Item* aLayer0=oItemTree;
{
Item* aLayer1;
aLayer1=pushItem(aLayer0, u8"収入", u8"円");
{
pushItem(aLayer1, u8"給料", u8"円");
pushItem(aLayer1, u8"雑収入", u8"円");
}
aLayer1=pushItem(aLayer0, u8"支出");
{
Item* aLayer2;
aLayer2=pushItem(aLayer1, u8"主食");
{
pushItem(aLayer2, u8"お米", u8"g", false, emtCount, 1000);
pushItem(aLayer2, u8"パン", u8"枚", false, emtCount, 1);
}
aLayer2=pushItem(aLayer1, u8"副食");
{
pushItem(aLayer2, u8"肉魚", u8"g", false, emtCount, 300);
pushItem(aLayer2, u8"野菜", u8"g", false, emtCount, 400);
pushItem(aLayer2, u8"果物");
}
}
aLayer1=pushItem(aLayer0, u8"現金", u8"円", true);
{
pushItem(aLayer1, u8"財布", u8"円", true, emtMoney, 35592);
pushItem(aLayer1, u8"預金", u8"円", true, emtMoney, 147135);
}
aLayer1=pushItem(aLayer0, u8"消費");
{
pushItem(aLayer1, u8"利用");
pushItem(aLayer1, u8"廃棄");
}
}
}

//—————————————————————————-
// 取引リスト設定
//—————————————————————————-

// —<<< 取引設定サブ >>>—

bool pushTrade
(
HouseholdAccounts* oHA,
short iYear,
char iMonth,
char iDay,
char const* iDebitName,
int iDebitAmount,
int iCreditAmount,
char const* iCreditName,
char const* iNote
)
{
Trade aTrade;
aTrade.mDate.mYear = iYear;
aTrade.mDate.mMonth = iMonth;
aTrade.mDate.mDay = iDay;
aTrade.mDebitItem = find(&(oHA->mItemTree), iDebitName);
aTrade.mDebitAmount = iDebitAmount;
aTrade.mCreditAmount= iCreditAmount;
aTrade.mCreditItem = find(&(oHA->mItemTree), iCreditName);
aTrade.mNote = iNote;

if (aTrade.mDebitItem == NULL)
{
std::cerr << theolizer::print(u8"商品名(%s)が不正です。", iDebitName) << std::endl;
return false;
}
if (aTrade.mCreditItem == NULL)
{
std::cerr << theolizer::print(u8"商品名(%s)が不正です。", iCreditName) << std::endl;
return false;
}

oHA->mTradeList.push_back(aTrade);
return true;
}

// —<<< 取引リスト設定 >>>—

void makeTrades(HouseholdAccounts* oHA)
{
pushTrade(oHA, 2016, 8,20, u8"利用", 300, 300, u8"お米", u8"");
pushTrade(oHA, 2016, 8,20, u8"利用", 300, 300, u8"肉魚", u8"牛肉");
pushTrade(oHA, 2016, 8,20, u8"廃棄", 400, 400, u8"野菜", u8"セロリ");
pushTrade(oHA, 2016, 8,22, u8"パン", 6, 158, u8"財布", u8"六切り1袋");
pushTrade(oHA, 2016, 8,22, u8"肉魚", 200, 269, u8"財布", u8"鶏肉200g");
pushTrade(oHA, 2016, 8,22, u8"野菜", 1200, 182, u8"財布", u8"キャベツ1玉");
pushTrade(oHA, 2016, 8,22, u8"果物", 0, 113, u8"財布", u8"バナナ1房");
pushTrade(oHA, 2016, 8,22, u8"利用", 3, 3, u8"パン", u8"食事");
pushTrade(oHA, 2016, 8,20, u8"利用", 200, 200, u8"肉魚", u8"鶏肉");
pushTrade(oHA, 2016, 8,22, u8"利用", 600, 600, u8"野菜", u8"キャベツ");
pushTrade(oHA, 2016, 8,25, u8"預金", 254536, 254536, u8"給料", u8"セオライド テクノロジー");
pushTrade(oHA, 2016, 8,25, u8"財布", 50000, 50000, u8"預金", u8"生活費");
pushTrade(oHA, 2016, 8,25, u8"お米", 10000, 4652, u8"財布", u8"こしひかり10Kg");
pushTrade(oHA, 2016, 8,25, u8"肉魚", 500, 685, u8"財布", u8"豚肉500g");
pushTrade(oHA, 2016, 8,25, u8"野菜", 200, 152, u8"財布", u8"ほうれん草");
pushTrade(oHA, 2016, 8,25, u8"野菜", 300, 136, u8"財布", u8"人参");
}

//—————————————————————————-
// 設定
//—————————————————————————-

void initialize(HouseholdAccounts* oHouseholdAccounts)
{
makeItems(&(oHouseholdAccounts->mItemTree));
makeTrades(oHouseholdAccounts);
}

// ***************************************************************************
// 家計簿表示
// ***************************************************************************

//—————————————————————————-
// 科目名結合
//—————————————————————————-

std::string getFullName(Item* iItem)
{
if (iItem->mParent != NULL)
{
return getFullName(iItem->mParent) + "/" + iItem->mName;
}
else
{
return iItem->mName;
}
}

//—————————————————————————-
// 科目表示
//—————————————————————————-

void displayItems(int iIndent, Item* iItem)
{
std::cout << std::string(iIndent*2, ‘ ‘) << iItem->mName;
switch(iItem->mManageType)
{
case emtMoney:
std::cout << u8" 残高:" << iItem->mAmount;
break;

case emtCount:
std::cout << u8" 在庫:" << iItem->mAmount;
break;
}
std::cout << "\n";
for (ChildIterator itr=iItem->mChildren.begin(); itr != iItem->mChildren.end(); ++itr)
{
displayItems(iIndent+1, &(*itr));
}
}

//—————————————————————————-
// 取引表示
//—————————————————————————-

void displayTrades(HouseholdAccounts* iHA)
{
for (TradeIterator itr=iHA->mTradeList.begin(); itr != iHA->mTradeList.end(); ++itr)
{
if (itr->mDebitAmount == itr->mCreditAmount)
{
std::cout << theolizer::print("%04d/%02d/%02d %s <- %s(%6d%2s) : %s\n",
itr->mDate.mYear,
itr->mDate.mMonth+0,
itr->mDate.mDay+0,
getFullName(itr->mDebitItem),
getFullName(itr->mCreditItem),
itr->mCreditAmount,
itr->mCreditItem->mUnit,
itr->mNote);
}
else
{
std::cout << theolizer::print("%04d/%02d/%02d %s(%6d%2s) <- %s(%6d%2s) : %s\n",
itr->mDate.mYear,
itr->mDate.mMonth+0,
itr->mDate.mDay+0,
getFullName(itr->mDebitItem),
itr->mDebitAmount,
itr->mDebitItem->mUnit,
getFullName(itr->mCreditItem),
itr->mCreditAmount,
itr->mCreditItem->mUnit,
itr->mNote);
}
}
}

//—————————————————————————-
// 全体表示
//—————————————————————————-

void display(HouseholdAccounts* iHouseholdAccounts)
{
std::cout << u8"— 科目 —\n";
displayItems(0, &(iHouseholdAccounts->mItemTree));

std::cout << u8"\n— 取引 —\n";
displayTrades(iHouseholdAccounts);
}

// ***************************************************************************
// 家計簿処理と結果表示
// ***************************************************************************

//—————————————————————————-
// 初期化
//—————————————————————————-

void clearIncrease(Item* iItem)
{
iItem->mAssetsIncrease=0;
for (ChildIterator itr=iItem->mChildren.begin(); itr != iItem->mChildren.end(); ++itr)
{
clearIncrease(&(*itr));
}
}

//—————————————————————————-
// 結果表示
//—————————————————————————-

void displayAmount(Item* iItem)
{
if (iItem->mAssetsIncrease)
{
std::cout << getFullName(iItem);
if (iItem->mIsAssets)
{
if (0 <= iItem->mAssetsIncrease)
{
std::cout << theolizer::print(u8" : %6d円の増加", iItem->mAssetsIncrease);
}
else
{
std::cout << theolizer::print(u8" : %6d円の減少", -iItem->mAssetsIncrease);
}
}
else
{
if (0 <= iItem->mAssetsIncrease)
{
std::cout << theolizer::print(u8" : %6d円の収入", iItem->mAssetsIncrease);
}
else
{
std::cout << theolizer::print(u8" : %6d円の支出", -iItem->mAssetsIncrease);
}
}

switch(iItem->mManageType)
{
case emtMoney:
std::cout << theolizer::print(u8" 残高は%6d%2s\n", iItem->mAmount, iItem->mUnit);
break;

case emtCount:
std::cout << theolizer::print(u8" 在庫は%6d%2s\n", iItem->mAmount, iItem->mUnit);
break;

default:
std::cout << "\n";
break;
}
}

for (ChildIterator itr=iItem->mChildren.begin(); itr != iItem->mChildren.end(); ++itr)
{
displayAmount(&(*itr));
}
}

//—————————————————————————-
// 計算
//—————————————————————————-

void calculate(HouseholdAccounts* ioHouseholdAccounts)
{
// 初期化
clearIncrease(&(ioHouseholdAccounts->mItemTree));

// 集計
for (TradeIterator itr=ioHouseholdAccounts->mTradeList.begin();
itr != ioHouseholdAccounts->mTradeList.end();
++itr)
{
// —<<< 増減処理 >>>—

// 金額を決定(資産が増える方をplus)
int aMoney=0;
if (itr->mDebitItem->mManageType == emtMoney)
{
aMoney=itr->mDebitAmount;
}
else if (itr->mCreditItem->mManageType == emtMoney)
{
aMoney=itr->mCreditAmount;
}

// 借方の資産は増える/借方の非資産は減る
for (Item* p=itr->mDebitItem; p != NULL; p=p->mParent)
{
if (p->mIsAssets)
{
p->mAssetsIncrease += aMoney;
}
else
{
p->mAssetsIncrease -= aMoney;
}
if (p->mManageType == emtCount)
{
p->mAmount += itr->mDebitAmount;
}
}

// 貸方の資産は減る/借方の非資産は増える
for (Item* p=itr->mCreditItem; p != NULL; p=p->mParent)
{
if (p->mIsAssets)
{
p->mAssetsIncrease -= aMoney;
}
else
{
p->mAssetsIncrease += aMoney;
}
if (p->mManageType == emtCount)
{
p->mAmount -= itr->mCreditAmount;
}
}

// —<<< 残高処理 >>>—

// 借方
if (itr->mDebitItem->mManageType == emtMoney)
{
itr->mDebitItem->mAmount += itr->mDebitAmount;
}

// 貸方
if (itr->mCreditItem->mManageType == emtMoney)
{
itr->mCreditItem->mAmount -= itr->mCreditAmount;
}
}

displayAmount(&(ioHouseholdAccounts->mItemTree));

}
[/cpp]

4-4.自動生成されたソース

main.cpp.theolizer.hpp
[cpp] #ifdef THEOLIZER_WRITE_CODE // ###### ManageType ######

#define THEOLIZER_GENERATED_LAST_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kLastVersionNo,1)
#define THEOLIZER_GENERATED_FULL_AUTO ManageType

// —<<< Version.1 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,1)
#define THEOLIZER_GENERATED_ENUM_NAME u8"ManageType"
#define THEOLIZER_GENERATED_SAVE_TYPE estName
#define THEOLIZER_GENERATED_BASE_TYPE int
#define THEOLIZER_GENERATED_ENUM_LIST()\
THEOLIZER_GENERATED_ELEMENT((u8"emtNone"),(0),(0))\
THEOLIZER_GENERATED_ELEMENT((u8"emtMoney"),(1),(1))\
THEOLIZER_GENERATED_ELEMENT((u8"emtCount"),(2),(2))
#define THEOLIZER_GENERATED_DEFAULT_VALUE 0
#include <theolizer/internal/version_enum.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

#endif//THEOLIZER_WRITE_CODE // ###### ManageType ######

#ifdef THEOLIZER_WRITE_CODE // ###### Item ######

#define THEOLIZER_GENERATED_LAST_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kLastVersionNo,2)
#define THEOLIZER_GENERATED_CLASS_TYPE THEOLIZER_INTERNAL_UNPAREN(Item)

// —<<< Version.2 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,2)
#define THEOLIZER_GENERATED_CLASS_NAME()\
THEOLIZER_INTERNAL_CLASS_NAME((u8"Item"))
#define THEOLIZER_GENERATED_ELEMENT_MAP emName
#define THEOLIZER_GENERATED_ELEMENT_LIST()\
THEOLIZER_INTERNAL_ELEMENT_N((mParent),mParent,etmDefault,\
(theolizerD::Settings),\
(Item *))\
THEOLIZER_INTERNAL_ELEMENT_N((mName),mName,etmDefault,\
(theolizerD::Settings),\
(std::string))\
THEOLIZER_INTERNAL_ELEMENT_N((mIsAssets),mIsAssets,etmDefault,\
(theolizerD::Settings),\
(bool))\
THEOLIZER_INTERNAL_ELEMENT_KN((mManageType),mManageType,etmDefault,\
(theolizerD::Settings),\
(ManageType),1)\
THEOLIZER_INTERNAL_ELEMENT_N((mAmount),mAmount,etmDefault,\
(theolizerD::Data),\
(int))\
THEOLIZER_INTERNAL_ELEMENT_N((mUnit),mUnit,etmDefault,\
(theolizerD::Settings),\
(std::string))\
THEOLIZER_INTERNAL_ELEMENT_N((mChildren),mChildren,etmDefault,\
(theolizerD::All),\
(theolizer::ListPointee<Item>))
#include <theolizer/internal/version_auto.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

// —<<< Version.1 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,1)
#define THEOLIZER_GENERATED_CLASS_NAME()\
THEOLIZER_INTERNAL_CLASS_NAME((u8"Item"))
#define THEOLIZER_GENERATED_ELEMENT_MAP emName
#define THEOLIZER_GENERATED_ELEMENT_LIST()\
THEOLIZER_INTERNAL_ELEMENT_N((mParent),mParent,etmDefault,\
(theolizerD::Settings),\
(Item *))\
THEOLIZER_INTERNAL_ELEMENT_N((mName),mName,etmDefault,\
(theolizerD::Settings),\
(std::string))\
THEOLIZER_INTERNAL_ELEMENT_N((mIsAssets),mIsAssets,etmDefault,\
(theolizerD::Settings),\
(bool))\
THEOLIZER_INTERNAL_ELEMENT_N_DEL((mDoManage),,etmDefault,\
(theolizerD::Settings),\
(bool))\
THEOLIZER_INTERNAL_ELEMENT_N((mAmount),mAmount,etmDefault,\
(theolizerD::Data),\
(int))\
THEOLIZER_INTERNAL_ELEMENT_N((mChildren),mChildren,etmDefault,\
(theolizerD::All),\
(theolizer::ListPointee<Item>))
#include <theolizer/internal/version_auto.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

#endif//THEOLIZER_WRITE_CODE // ###### Item ######

#ifdef THEOLIZER_WRITE_CODE // ###### Date ######

#define THEOLIZER_GENERATED_LAST_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kLastVersionNo,1)
#define THEOLIZER_GENERATED_FULL_AUTO Date

// —<<< Version.1 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,1)
#define THEOLIZER_GENERATED_CLASS_NAME()\
THEOLIZER_INTERNAL_CLASS_NAME((u8"Date"))
#define THEOLIZER_GENERATED_ELEMENT_MAP emName
#define THEOLIZER_GENERATED_ELEMENT_LIST()\
THEOLIZER_INTERNAL_ELEMENT_N((mYear),mYear,etmDefault,\
(theolizerD::All),\
(short))\
THEOLIZER_INTERNAL_ELEMENT_N((mMonth),mMonth,etmDefault,\
(theolizerD::All),\
(char))\
THEOLIZER_INTERNAL_ELEMENT_N((mDay),mDay,etmDefault,\
(theolizerD::All),\
(char))
#include <theolizer/internal/version_auto.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

#endif//THEOLIZER_WRITE_CODE // ###### Date ######

#ifdef THEOLIZER_WRITE_CODE // ###### Trade ######

#define THEOLIZER_GENERATED_LAST_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kLastVersionNo,2)
#define THEOLIZER_GENERATED_CLASS_TYPE THEOLIZER_INTERNAL_UNPAREN(Trade)

// —<<< Version.2 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,2)
#define THEOLIZER_GENERATED_CLASS_NAME()\
THEOLIZER_INTERNAL_CLASS_NAME((u8"Trade"))
#define THEOLIZER_GENERATED_ELEMENT_MAP emName
#define THEOLIZER_GENERATED_ELEMENT_LIST()\
THEOLIZER_INTERNAL_ELEMENT_KN((mDate),mDate,etmDefault,\
(theolizerD::All),\
(Date),1)\
THEOLIZER_INTERNAL_ELEMENT_N((mDebitItem),mDebitItem,etmDefault,\
(theolizerD::All),\
(Item *))\
THEOLIZER_INTERNAL_ELEMENT_N((mDebitAmount),mDebitAmount,etmDefault,\
(theolizerD::All),\
(int))\
THEOLIZER_INTERNAL_ELEMENT_N((mCreditAmount),mCreditAmount,etmDefault,\
(theolizerD::All),\
(int))\
THEOLIZER_INTERNAL_ELEMENT_N((mCreditItem),mCreditItem,etmDefault,\
(theolizerD::All),\
(Item *))\
THEOLIZER_INTERNAL_ELEMENT_N((mNote),mNote,etmDefault,\
(theolizerD::All),\
(std::string))
#include <theolizer/internal/version_auto.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

// —<<< Version.1 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,1)
#define THEOLIZER_GENERATED_CLASS_NAME()\
THEOLIZER_INTERNAL_CLASS_NAME((u8"Trade"))
#define THEOLIZER_GENERATED_ELEMENT_MAP emName
#define THEOLIZER_GENERATED_ELEMENT_LIST()\
THEOLIZER_INTERNAL_ELEMENT_KN((mDate),mDate,etmDefault,\
(theolizerD::All),\
(Date),1)\
THEOLIZER_INTERNAL_ELEMENT_N((mDebitItem),mDebitItem,etmDefault,\
(theolizerD::All),\
(Item *))\
THEOLIZER_INTERNAL_ELEMENT_N_DEL((mAmount),,etmDefault,\
(theolizerD::All),\
(int))\
THEOLIZER_INTERNAL_ELEMENT_N((mCreditItem),mCreditItem,etmDefault,\
(theolizerD::All),\
(Item *))\
THEOLIZER_INTERNAL_ELEMENT_N((mNote),mNote,etmDefault,\
(theolizerD::All),\
(std::string))
#include <theolizer/internal/version_auto.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

#endif//THEOLIZER_WRITE_CODE // ###### Trade ######

#ifdef THEOLIZER_WRITE_CODE // ###### HouseholdAccounts ######

#define THEOLIZER_GENERATED_LAST_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kLastVersionNo,2)
#define THEOLIZER_GENERATED_CLASS_TYPE THEOLIZER_INTERNAL_UNPAREN(HouseholdAccounts)

// —<<< Version.2 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,2)
#define THEOLIZER_GENERATED_CLASS_NAME()\
THEOLIZER_INTERNAL_CLASS_NAME((u8"HouseholdAccounts"))
#define THEOLIZER_GENERATED_ELEMENT_MAP emName
#define THEOLIZER_GENERATED_ELEMENT_LIST()\
THEOLIZER_INTERNAL_ELEMENT_KI((mItemTree),mItemTree,etmPointee,\
(theolizerD::All),\
(Item),2)\
THEOLIZER_INTERNAL_ELEMENT_N((mTradeList),mTradeList,etmDefault,\
(theolizerD::Data),\
(std::list<Trade>))
#include <theolizer/internal/version_auto.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

// —<<< Version.1 >>>—

#define THEOLIZER_GENERATED_VERSION_NO THEOLIZER_INTERNAL_DEFINE(kVersionNo,1)
#define THEOLIZER_GENERATED_CLASS_NAME()\
THEOLIZER_INTERNAL_CLASS_NAME((u8"HouseholdAccounts"))
#define THEOLIZER_GENERATED_ELEMENT_MAP emName
#define THEOLIZER_GENERATED_ELEMENT_LIST()\
THEOLIZER_INTERNAL_ELEMENT_KI((mItemTree),mItemTree,etmPointee,\
(theolizerD::All),\
(Item),1)\
THEOLIZER_INTERNAL_ELEMENT_N((mTradeList),mTradeList,etmDefault,\
(theolizerD::Data),\
(std::list<Trade>))
#include <theolizer/internal/version_auto.inc>
#undef THEOLIZER_GENERATED_VERSION_NO

#endif//THEOLIZER_WRITE_CODE // ###### HouseholdAccounts ######

#ifdef THEOLIZER_WRITE_CODE // ###### Global VersionNo. Table ######

namespace theolizer{namespace internal{
namespace global_table{
GlobalVersionTable::GlobalVersionTable()
{
THEOLIZER_INTERNAL_ADD(theolizer::internal::JsonMidOSerializer,1u,1u);
THEOLIZER_INTERNAL_ADD(theolizer::internal::JsonMidISerializer,1u,1u);
THEOLIZER_INTERNAL_ADD(pairTheolizer,1u,1u);
THEOLIZER_INTERNAL_ADD(listTheolizer,1u,1u);
THEOLIZER_INTERNAL_ADD(ListPointeeTheolizer,1u,1u);
THEOLIZER_INTERNAL_ADD(Item,1u,2u);
THEOLIZER_INTERNAL_ADD(Trade,1u,2u);
THEOLIZER_INTERNAL_ADD(HouseholdAccounts,1u,2u);
}
} // namespace global_table
}} // namespace theolizer

#endif//THEOLIZER_WRITE_CODE // ###### Global VersionNo. Table ######
[/cpp]

4-5.CMakeLists.txt

CMakeLists.txt
[text] #[[###########################################################################
Theolizer紹介用サンプルCMakeLists.txt
]]############################################################################

if("${CMAKE_VERSION}" STREQUAL "")
set(CMAKE_VERSION, 3.5.0)
endif()
cmake_minimum_required(VERSION ${CMAKE_VERSION})

message(STATUS "BOOST_ROOT=${BOOST_ROOT}")

#—————————————————————————–
# プロジェクト設定
#—————————————————————————–

set(TARGET_NAME sample)
set(SOURCE_LIST main.cpp sub.cpp)
set(HEADER_LIST common.h)

project(${TARGET_NAME} VERSION 1.0.0)

#—————————————————————————–
# ビルド設定
#—————————————————————————–

# MSVCの通常使わないビルド・モードとZERO_CHECKプロジェクトの削除
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE)
set(CMAKE_SUPPRESS_REGENERATION TRUE)

# Theolizer
find_package(THEOLIZER)

# Options
if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
add_definitions(-D_UNICODE -DUNICODE)
set(CMAKE_DEBUG_POSTFIX "d")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

# MinGWの不具合(https://sourceforge.net/p/mingw-w64/discussion/723797/thread/c6b70624/#7f0a)暫定対処
if((CMAKE_COMPILER_IS_MINGW) AND (CMAKE_SIZEOF_VOID_P EQUAL 8))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
endif()
endif()

# example
add_executable(${TARGET_NAME} ${SOURCE_LIST} ${HEADER_LIST})
setup_theolizer(${TARGET_NAME} StaticWithBoost)

#—————————————————————————–
# テスト実行
#—————————————————————————–

enable_testing()
add_test(NAME ${TARGET_NAME} COMMAND $<TARGET_FILE:${TARGET_NAME}>)

add_custom_target(BuildTest COMMAND "ctest" "-V" "-C" $<CONFIG>)
add_dependencies(BuildTest ${TARGET_NAME})
[/text]

5.実行結果

5-1.新プログラムにてバージョン2で保存/回復

パラメータ無しで起動した場合の結果です。バージョン2のデータが保存され回復されました。

5-1-1.保存された設定ファイル
Settings2.json
[text] {
"SerialzierName":"JsonTheolizer",
"GlobalVersionNo":2,
"TypeInfoList":[1] }
{
"mItemTree":[1,{
"mParent":0,
"mName":"家計",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
4,
[2,{
"mParent":1,
"mName":"収入",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"円",
"mChildren":[
2,
[3,{
"mParent":2,
"mName":"給料",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"円",
"mChildren":[
0
] }],
[4,{
"mParent":2,
"mName":"雑収入",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"円",
"mChildren":[
0
] }] ] }],
[5,{
"mParent":1,
"mName":"支出",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
2,
[6,{
"mParent":5,
"mName":"主食",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
2,
[7,{
"mParent":6,
"mName":"お米",
"mIsAssets":0,
"mManageType":"emtCount",
"mUnit":"g",
"mChildren":[
0
] }],
[8,{
"mParent":6,
"mName":"パン",
"mIsAssets":0,
"mManageType":"emtCount",
"mUnit":"枚",
"mChildren":[
0
] }] ] }],
[9,{
"mParent":5,
"mName":"副食",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
3,
[10,{
"mParent":9,
"mName":"肉魚",
"mIsAssets":0,
"mManageType":"emtCount",
"mUnit":"g",
"mChildren":[
0
] }],
[11,{
"mParent":9,
"mName":"野菜",
"mIsAssets":0,
"mManageType":"emtCount",
"mUnit":"g",
"mChildren":[
0
] }],
[12,{
"mParent":9,
"mName":"果物",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
0
] }] ] }] ] }],
[13,{
"mParent":1,
"mName":"現金",
"mIsAssets":1,
"mManageType":"emtNone",
"mUnit":"円",
"mChildren":[
2,
[14,{
"mParent":13,
"mName":"財布",
"mIsAssets":1,
"mManageType":"emtMoney",
"mUnit":"円",
"mChildren":[
0
] }],
[15,{
"mParent":13,
"mName":"預金",
"mIsAssets":1,
"mManageType":"emtMoney",
"mUnit":"円",
"mChildren":[
0
] }] ] }],
[16,{
"mParent":1,
"mName":"消費",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
2,
[17,{
"mParent":16,
"mName":"利用",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
0
] }],
[18,{
"mParent":16,
"mName":"廃棄",
"mIsAssets":0,
"mManageType":"emtNone",
"mUnit":"",
"mChildren":[
0
] }] ] }] ] }] }
[/text]
5-1-2.保存されたデータファイル
Data2.json
[text] {
"SerialzierName":"JsonTheolizer",
"GlobalVersionNo":2,
"TypeInfoList":[1] }
{
"mItemTree":[1,{
"mAmount":0,
"mChildren":[
4,
[2,{
"mAmount":0,
"mChildren":[
2,
[3,{
"mAmount":0,
"mChildren":[
0
] }],
[4,{
"mAmount":0,
"mChildren":[
0
] }] ] }],
[5,{
"mAmount":0,
"mChildren":[
2,
[6,{
"mAmount":0,
"mChildren":[
2,
[7,{
"mAmount":1000,
"mChildren":[
0
] }],
[8,{
"mAmount":1,
"mChildren":[
0
] }] ] }],
[9,{
"mAmount":0,
"mChildren":[
3,
[10,{
"mAmount":300,
"mChildren":[
0
] }],
[11,{
"mAmount":400,
"mChildren":[
0
] }],
[12,{
"mAmount":0,
"mChildren":[
0
] }] ] }] ] }],
[13,{
"mAmount":0,
"mChildren":[
2,
[14,{
"mAmount":35592,
"mChildren":[
0
] }],
[15,{
"mAmount":147135,
"mChildren":[
0
] }] ] }],
[16,{
"mAmount":0,
"mChildren":[
2,
[17,{
"mAmount":0,
"mChildren":[
0
] }],
[18,{
"mAmount":0,
"mChildren":[
0
] }] ] }] ] }],
"mTradeList":[
16,
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":17,
"mDebitAmount":300,
"mCreditAmount":300,
"mCreditItem":7,
"mNote":""
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":17,
"mDebitAmount":300,
"mCreditAmount":300,
"mCreditItem":10,
"mNote":"牛肉"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":18,
"mDebitAmount":400,
"mCreditAmount":400,
"mCreditItem":11,
"mNote":"セロリ"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":8,
"mDebitAmount":6,
"mCreditAmount":158,
"mCreditItem":14,
"mNote":"六切り1袋"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":10,
"mDebitAmount":200,
"mCreditAmount":269,
"mCreditItem":14,
"mNote":"鶏肉200g"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":11,
"mDebitAmount":1200,
"mCreditAmount":182,
"mCreditItem":14,
"mNote":"キャベツ1玉"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":12,
"mDebitAmount":0,
"mCreditAmount":113,
"mCreditItem":14,
"mNote":"バナナ1房"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":17,
"mDebitAmount":3,
"mCreditAmount":3,
"mCreditItem":8,
"mNote":"食事"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":17,
"mDebitAmount":200,
"mCreditAmount":200,
"mCreditItem":10,
"mNote":"鶏肉"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":17,
"mDebitAmount":600,
"mCreditAmount":600,
"mCreditItem":11,
"mNote":"キャベツ"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":15,
"mDebitAmount":254536,
"mCreditAmount":254536,
"mCreditItem":3,
"mNote":"セオライド テクノロジー"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":14,
"mDebitAmount":50000,
"mCreditAmount":50000,
"mCreditItem":15,
"mNote":"生活費"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":7,
"mDebitAmount":10000,
"mCreditAmount":4652,
"mCreditItem":14,
"mNote":"こしひかり10Kg"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":10,
"mDebitAmount":500,
"mCreditAmount":685,
"mCreditItem":14,
"mNote":"豚肉500g"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":11,
"mDebitAmount":200,
"mCreditAmount":152,
"mCreditItem":14,
"mNote":"ほうれん草"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":11,
"mDebitAmount":300,
"mCreditAmount":136,
"mCreditItem":14,
"mNote":"人参"
}
] }
[/text]
5-1-3.実行結果
result2.log
[text] GlobalVersionNo=2 LoadOnly:0
Files : Settings2.json, Data2.json
<<< 保存するサンプル・データ >>>
— 科目 —
家計
収入
給料
雑収入
支出
主食
お米 在庫:1000
パン 在庫:1
副食
肉魚 在庫:300
野菜 在庫:400
果物
現金
財布 残高:35592
預金 残高:147135
消費
利用
廃棄

— 取引 —
2016/08/20 家計/消費/利用 <- 家計/支出/主食/お米( 300 g) :
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 300 g) : 牛肉
2016/08/20 家計/消費/廃棄 <- 家計/支出/副食/野菜( 400 g) : セロリ
2016/08/22 家計/支出/主食/パン( 6枚) <- 家計/現金/財布( 158円) : 六切り1袋
2016/08/22 家計/支出/副食/肉魚( 200 g) <- 家計/現金/財布( 269円) : 鶏肉200g
2016/08/22 家計/支出/副食/野菜( 1200 g) <- 家計/現金/財布( 182円) : キャベツ1玉
2016/08/22 家計/支出/副食/果物( 0 ) <- 家計/現金/財布( 113円) : バナナ1房
2016/08/22 家計/消費/利用 <- 家計/支出/主食/パン( 3枚) : 食事
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 200 g) : 鶏肉
2016/08/22 家計/消費/利用 <- 家計/支出/副食/野菜( 600 g) : キャベツ
2016/08/25 家計/現金/預金 <- 家計/収入/給料(254536円) : セオライド テクノロジー
2016/08/25 家計/現金/財布 <- 家計/現金/預金( 50000円) : 生活費
2016/08/25 家計/支出/主食/お米( 10000 g) <- 家計/現金/財布( 4652円) : こしひかり10Kg
2016/08/25 家計/支出/副食/肉魚( 500 g) <- 家計/現金/財布( 685円) : 豚肉500g
2016/08/25 家計/支出/副食/野菜( 200 g) <- 家計/現金/財布( 152円) : ほうれん草
2016/08/25 家計/支出/副食/野菜( 300 g) <- 家計/現金/財布( 136円) : 人参

<<< 回復したサンプル・データ >>>
— 科目 —
家計
収入
給料
雑収入
支出
主食
お米 在庫:1000
パン 在庫:1
副食
肉魚 在庫:300
野菜 在庫:400
果物
現金
財布 残高:35592
預金 残高:147135
消費
利用
廃棄

— 取引 —
2016/08/20 家計/消費/利用 <- 家計/支出/主食/お米( 300 g) :
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 300 g) : 牛肉
2016/08/20 家計/消費/廃棄 <- 家計/支出/副食/野菜( 400 g) : セロリ
2016/08/22 家計/支出/主食/パン( 6枚) <- 家計/現金/財布( 158円) : 六切り1袋
2016/08/22 家計/支出/副食/肉魚( 200 g) <- 家計/現金/財布( 269円) : 鶏肉200g
2016/08/22 家計/支出/副食/野菜( 1200 g) <- 家計/現金/財布( 182円) : キャベツ1玉
2016/08/22 家計/支出/副食/果物( 0 ) <- 家計/現金/財布( 113円) : バナナ1房
2016/08/22 家計/消費/利用 <- 家計/支出/主食/パン( 3枚) : 食事
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 200 g) : 鶏肉
2016/08/22 家計/消費/利用 <- 家計/支出/副食/野菜( 600 g) : キャベツ
2016/08/25 家計/現金/預金 <- 家計/収入/給料(254536円) : セオライド テクノロジー
2016/08/25 家計/現金/財布 <- 家計/現金/預金( 50000円) : 生活費
2016/08/25 家計/支出/主食/お米( 10000 g) <- 家計/現金/財布( 4652円) : こしひかり10Kg
2016/08/25 家計/支出/副食/肉魚( 500 g) <- 家計/現金/財布( 685円) : 豚肉500g
2016/08/25 家計/支出/副食/野菜( 200 g) <- 家計/現金/財布( 152円) : ほうれん草
2016/08/25 家計/支出/副食/野菜( 300 g) <- 家計/現金/財布( 136円) : 人参

<<< サンプルの集計結果 >>>
家計/収入 : 254536円の収入
家計/収入/給料 : 254536円の収入
家計/支出 : 6347円の支出
家計/支出/主食 : 4810円の支出
家計/支出/主食/お米 : 4652円の支出 在庫は 10700 g
家計/支出/主食/パン : 158円の支出 在庫は 4枚
家計/支出/副食 : 1537円の支出
家計/支出/副食/肉魚 : 954円の支出 在庫は 500 g
家計/支出/副食/野菜 : 470円の支出 在庫は 1100 g
家計/支出/副食/果物 : 113円の支出
家計/現金 : 248189円の増加
家計/現金/財布 : 43653円の増加 残高は 79245円
家計/現金/預金 : 204536円の増加 残高は351671円
[/text]

5-2.旧プログラムのファイルを回復する(新プログラムにてバージョン1形式を回復)

第3回の技術解説で作成した旧プログラムにて保存したSettings.jsonとData.Jsonを新プログラムで回復します。
新プログラムをコマンドライン・パラメータにLを指定して起動した結果です。

5-2-1.回復した設定ファイル
Settings.json
[text] {
"SerialzierName":"JsonTheolizer",
"GlobalVersionNo":1,
"TypeInfoList":[1] }
{
"mItemTree":[1,{
"mParent":0,
"mName":"家計",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
3,
[2,{
"mParent":1,
"mName":"収入",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
2,
[3,{
"mParent":2,
"mName":"給料",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[4,{
"mParent":2,
"mName":"雑収入",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }] ] }],
[5,{
"mParent":1,
"mName":"支出",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
2,
[6,{
"mParent":5,
"mName":"主食",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
2,
[7,{
"mParent":6,
"mName":"お米",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[8,{
"mParent":6,
"mName":"パン",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }] ] }],
[9,{
"mParent":5,
"mName":"副食",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
3,
[10,{
"mParent":9,
"mName":"肉魚",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[11,{
"mParent":9,
"mName":"野菜",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[12,{
"mParent":9,
"mName":"果物",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }] ] }] ] }],
[13,{
"mParent":1,
"mName":"現金",
"mIsAssets":1,
"mDoManage":0,
"mChildren":[
2,
[14,{
"mParent":13,
"mName":"財布",
"mIsAssets":1,
"mDoManage":1,
"mChildren":[
0
] }],
[15,{
"mParent":13,
"mName":"預金",
"mIsAssets":1,
"mDoManage":1,
"mChildren":[
0
] }] ] }] ] }] }
[/text]
5-2-2.回復したデータファイル
Data.json
[text] {
"SerialzierName":"JsonTheolizer",
"GlobalVersionNo":1,
"TypeInfoList":[1] }
{
"mItemTree":[1,{
"mAmount":0,
"mChildren":[
3,
[2,{
"mAmount":0,
"mChildren":[
2,
[3,{
"mAmount":0,
"mChildren":[
0
] }],
[4,{
"mAmount":0,
"mChildren":[
0
] }] ] }],
[5,{
"mAmount":0,
"mChildren":[
2,
[6,{
"mAmount":0,
"mChildren":[
2,
[7,{
"mAmount":0,
"mChildren":[
0
] }],
[8,{
"mAmount":0,
"mChildren":[
0
] }] ] }],
[9,{
"mAmount":0,
"mChildren":[
3,
[10,{
"mAmount":0,
"mChildren":[
0
] }],
[11,{
"mAmount":0,
"mChildren":[
0
] }],
[12,{
"mAmount":0,
"mChildren":[
0
] }] ] }] ] }],
[13,{
"mAmount":0,
"mChildren":[
2,
[14,{
"mAmount":35592,
"mChildren":[
0
] }],
[15,{
"mAmount":147135,
"mChildren":[
0
] }] ] }] ] }],
"mTradeList":[
10,
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":8,
"mAmount":158,
"mCreditItem":14,
"mNote":"六切り1袋"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":10,
"mAmount":269,
"mCreditItem":14,
"mNote":"鶏肉200g"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":11,
"mAmount":182,
"mCreditItem":14,
"mNote":"キャベツ1玉"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":12,
"mAmount":113,
"mCreditItem":14,
"mNote":"バナナ1房"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":15,
"mAmount":254536,
"mCreditItem":3,
"mNote":"セオライド テクノロジー"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":14,
"mAmount":50000,
"mCreditItem":15,
"mNote":"生活費"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":7,
"mAmount":4652,
"mCreditItem":14,
"mNote":"こしひかり10Kg"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":10,
"mAmount":685,
"mCreditItem":14,
"mNote":"豚肉500g"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":11,
"mAmount":152,
"mCreditItem":14,
"mNote":"ほうれん草"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":11,
"mAmount":136,
"mCreditItem":14,
"mNote":"人参"
}
] }
[/text]
5-2-3.実行結果
result2L.log
[text] LoadOnly:1
Files : Settings.json, Data.json

<<< 回復したサンプル・データ >>>
— 科目 —
家計
収入
給料
雑収入
支出
主食
お米
パン
副食
肉魚
野菜
果物
現金
財布 残高:35592
預金 残高:147135

— 取引 —
2016/08/22 家計/支出/主食/パン <- 家計/現金/財布( 158 ) : 六切り1袋
2016/08/22 家計/支出/副食/肉魚 <- 家計/現金/財布( 269 ) : 鶏肉200g
2016/08/22 家計/支出/副食/野菜 <- 家計/現金/財布( 182 ) : キャベツ1玉
2016/08/22 家計/支出/副食/果物 <- 家計/現金/財布( 113 ) : バナナ1房
2016/08/22 家計/現金/預金 <- 家計/収入/給料(254536 ) : セオライド テクノロジー
2016/08/25 家計/現金/財布 <- 家計/現金/預金( 50000 ) : 生活費
2016/08/25 家計/支出/主食/お米 <- 家計/現金/財布( 4652 ) : こしひかり10Kg
2016/08/25 家計/支出/副食/肉魚 <- 家計/現金/財布( 685 ) : 豚肉500g
2016/08/25 家計/支出/副食/野菜 <- 家計/現金/財布( 152 ) : ほうれん草
2016/08/25 家計/支出/副食/野菜 <- 家計/現金/財布( 136 ) : 人参

<<< サンプルの集計結果 >>>
家計/収入 : 254536円の収入
家計/収入/給料 : 254536円の収入
家計/支出 : 6347円の支出
家計/支出/主食 : 4810円の支出
家計/支出/主食/お米 : 4652円の支出
家計/支出/主食/パン : 158円の支出
家計/支出/副食 : 1537円の支出
家計/支出/副食/肉魚 : 954円の支出
家計/支出/副食/野菜 : 470円の支出
家計/支出/副食/果物 : 113円の支出
家計/現金 : 248189円の増加
家計/現金/財布 : 43653円の増加 残高は 79245
家計/現金/預金 : 204536円の増加 残高は351671
[/text]

5-3.旧プログラムで回復できるファイルを保存する(新プログラムにてバージョン1を保存し、旧プログラムで回復)

新プログラムをコマンドライン・パラメータに1を指定して起動することでバージョン1のデータが保存されます。
そして、旧プログラムを起動し、このデータを読ませた結果です。

5-3-1.保存された設定ファイル
Settings1.json
[text] {
"SerialzierName":"JsonTheolizer",
"GlobalVersionNo":1,
"TypeInfoList":[1] }
{
"mItemTree":[1,{
"mParent":0,
"mName":"家計",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
4,
[2,{
"mParent":1,
"mName":"収入",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
2,
[3,{
"mParent":2,
"mName":"給料",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[4,{
"mParent":2,
"mName":"雑収入",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }] ] }],
[5,{
"mParent":1,
"mName":"支出",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
2,
[6,{
"mParent":5,
"mName":"主食",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
2,
[7,{
"mParent":6,
"mName":"お米",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[8,{
"mParent":6,
"mName":"パン",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }] ] }],
[9,{
"mParent":5,
"mName":"副食",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
3,
[10,{
"mParent":9,
"mName":"肉魚",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[11,{
"mParent":9,
"mName":"野菜",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[12,{
"mParent":9,
"mName":"果物",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }] ] }] ] }],
[13,{
"mParent":1,
"mName":"現金",
"mIsAssets":1,
"mDoManage":0,
"mChildren":[
2,
[14,{
"mParent":13,
"mName":"財布",
"mIsAssets":1,
"mDoManage":1,
"mChildren":[
0
] }],
[15,{
"mParent":13,
"mName":"預金",
"mIsAssets":1,
"mDoManage":1,
"mChildren":[
0
] }] ] }],
[16,{
"mParent":1,
"mName":"消費",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
2,
[17,{
"mParent":16,
"mName":"利用",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }],
[18,{
"mParent":16,
"mName":"廃棄",
"mIsAssets":0,
"mDoManage":0,
"mChildren":[
0
] }] ] }] ] }] }
[/text]
5-3-2.保存されたデータファイル
Data1.json
[text] {
"SerialzierName":"JsonTheolizer",
"GlobalVersionNo":1,
"TypeInfoList":[1] }
{
"mItemTree":[1,{
"mAmount":0,
"mChildren":[
4,
[2,{
"mAmount":0,
"mChildren":[
2,
[3,{
"mAmount":0,
"mChildren":[
0
] }],
[4,{
"mAmount":0,
"mChildren":[
0
] }] ] }],
[5,{
"mAmount":0,
"mChildren":[
2,
[6,{
"mAmount":0,
"mChildren":[
2,
[7,{
"mAmount":0,
"mChildren":[
0
] }],
[8,{
"mAmount":0,
"mChildren":[
0
] }] ] }],
[9,{
"mAmount":0,
"mChildren":[
3,
[10,{
"mAmount":0,
"mChildren":[
0
] }],
[11,{
"mAmount":0,
"mChildren":[
0
] }],
[12,{
"mAmount":0,
"mChildren":[
0
] }] ] }] ] }],
[13,{
"mAmount":0,
"mChildren":[
2,
[14,{
"mAmount":35592,
"mChildren":[
0
] }],
[15,{
"mAmount":147135,
"mChildren":[
0
] }] ] }],
[16,{
"mAmount":0,
"mChildren":[
2,
[17,{
"mAmount":0,
"mChildren":[
0
] }],
[18,{
"mAmount":0,
"mChildren":[
0
] }] ] }] ] }],
"mTradeList":[
16,
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":17,
"mAmount":0,
"mCreditItem":7,
"mNote":""
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":17,
"mAmount":0,
"mCreditItem":10,
"mNote":"牛肉"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":18,
"mAmount":0,
"mCreditItem":11,
"mNote":"セロリ"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":8,
"mAmount":158,
"mCreditItem":14,
"mNote":"六切り1袋"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":10,
"mAmount":269,
"mCreditItem":14,
"mNote":"鶏肉200g"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":11,
"mAmount":182,
"mCreditItem":14,
"mNote":"キャベツ1玉"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":12,
"mAmount":113,
"mCreditItem":14,
"mNote":"バナナ1房"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":17,
"mAmount":0,
"mCreditItem":8,
"mNote":"食事"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":20
},
"mDebitItem":17,
"mAmount":0,
"mCreditItem":10,
"mNote":"鶏肉"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":22
},
"mDebitItem":17,
"mAmount":0,
"mCreditItem":11,
"mNote":"キャベツ"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":15,
"mAmount":254536,
"mCreditItem":3,
"mNote":"セオライド テクノロジー"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":14,
"mAmount":50000,
"mCreditItem":15,
"mNote":"生活費"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":7,
"mAmount":4652,
"mCreditItem":14,
"mNote":"こしひかり10Kg"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":10,
"mAmount":685,
"mCreditItem":14,
"mNote":"豚肉500g"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":11,
"mAmount":152,
"mCreditItem":14,
"mNote":"ほうれん草"
},
{
"mDate":{
"mYear":2016,
"mMonth":8,
"mDay":25
},
"mDebitItem":11,
"mAmount":136,
"mCreditItem":14,
"mNote":"人参"
}
] }
[/text]
5-3-3.実行結果
result21.log
[text] GlobalVersionNo=1 LoadOnly:0
Files : Settings1.json, Data1.json
<<< 保存するサンプル・データ >>>
— 科目 —
家計
収入
給料
雑収入
支出
主食
お米 在庫:1000
パン 在庫:1
副食
肉魚 在庫:300
野菜 在庫:400
果物
現金
財布 残高:35592
預金 残高:147135
消費
利用
廃棄

— 取引 —
2016/08/20 家計/消費/利用 <- 家計/支出/主食/お米( 300 g) :
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 300 g) : 牛肉
2016/08/20 家計/消費/廃棄 <- 家計/支出/副食/野菜( 400 g) : セロリ
2016/08/22 家計/支出/主食/パン( 6枚) <- 家計/現金/財布( 158円) : 六切り1袋
2016/08/22 家計/支出/副食/肉魚( 200 g) <- 家計/現金/財布( 269円) : 鶏肉200g
2016/08/22 家計/支出/副食/野菜( 1200 g) <- 家計/現金/財布( 182円) : キャベツ1玉
2016/08/22 家計/支出/副食/果物( 0 ) <- 家計/現金/財布( 113円) : バナナ1房
2016/08/22 家計/消費/利用 <- 家計/支出/主食/パン( 3枚) : 食事
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 200 g) : 鶏肉
2016/08/22 家計/消費/利用 <- 家計/支出/副食/野菜( 600 g) : キャベツ
2016/08/25 家計/現金/預金 <- 家計/収入/給料(254536円) : セオライド テクノロジー
2016/08/25 家計/現金/財布 <- 家計/現金/預金( 50000円) : 生活費
2016/08/25 家計/支出/主食/お米( 10000 g) <- 家計/現金/財布( 4652円) : こしひかり10Kg
2016/08/25 家計/支出/副食/肉魚( 500 g) <- 家計/現金/財布( 685円) : 豚肉500g
2016/08/25 家計/支出/副食/野菜( 200 g) <- 家計/現金/財布( 152円) : ほうれん草
2016/08/25 家計/支出/副食/野菜( 300 g) <- 家計/現金/財布( 136円) : 人参

<<< 回復したサンプル・データ >>>
— 科目 —
家計
収入
給料
雑収入
支出
主食
お米
パン
副食
肉魚
野菜
果物
現金
財布 残高:35592
預金 残高:147135
消費
利用
廃棄

— 取引 —
2016/08/20 家計/消費/利用 <- 家計/支出/主食/お米( 0 ) :
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 0 ) : 牛肉
2016/08/20 家計/消費/廃棄 <- 家計/支出/副食/野菜( 0 ) : セロリ
2016/08/22 家計/支出/主食/パン <- 家計/現金/財布( 158 ) : 六切り1袋
2016/08/22 家計/支出/副食/肉魚 <- 家計/現金/財布( 269 ) : 鶏肉200g
2016/08/22 家計/支出/副食/野菜 <- 家計/現金/財布( 182 ) : キャベツ1玉
2016/08/22 家計/支出/副食/果物 <- 家計/現金/財布( 113 ) : バナナ1房
2016/08/22 家計/消費/利用 <- 家計/支出/主食/パン( 0 ) : 食事
2016/08/20 家計/消費/利用 <- 家計/支出/副食/肉魚( 0 ) : 鶏肉
2016/08/22 家計/消費/利用 <- 家計/支出/副食/野菜( 0 ) : キャベツ
2016/08/25 家計/現金/預金 <- 家計/収入/給料(254536 ) : セオライド テクノロジー
2016/08/25 家計/現金/財布 <- 家計/現金/預金( 50000 ) : 生活費
2016/08/25 家計/支出/主食/お米 <- 家計/現金/財布( 4652 ) : こしひかり10Kg
2016/08/25 家計/支出/副食/肉魚 <- 家計/現金/財布( 685 ) : 豚肉500g
2016/08/25 家計/支出/副食/野菜 <- 家計/現金/財布( 152 ) : ほうれん草
2016/08/25 家計/支出/副食/野菜 <- 家計/現金/財布( 136 ) : 人参

<<< サンプルの集計結果 >>>
家計/収入 : 254536円の収入
家計/収入/給料 : 254536円の収入
家計/支出 : 6347円の支出
家計/支出/主食 : 4810円の支出
家計/支出/主食/お米 : 4652円の支出
家計/支出/主食/パン : 158円の支出
家計/支出/副食 : 1537円の支出
家計/支出/副食/肉魚 : 954円の支出
家計/支出/副食/野菜 : 470円の支出
家計/支出/副食/果物 : 113円の支出
家計/現金 : 248189円の増加
家計/現金/財布 : 43653円の増加 残高は 79245
家計/現金/預金 : 204536円の増加 残高は351671
[/text]

6.まとめ

Theolizer®の開発に当たって、クラス・構造体・enum型の仕様変更を容易にできることに注力しました。
バージョン・アップ/ダウン処理をカスケード処理すること、および、グローバル・バージョン番号テーブルの実装により、変更工数を大きく改善できると思います。