2021年2月8日月曜日

C#のオブジェクト配列をCSVに保存する/CSVから読み込む

時系列データのクラスオブジェクトをまるごとCSVファイルに保存する. 大量のファイルが生成されても一覧性が悪いのでクラスの構造はCSVのヘッダに埋め込んで,数値や文字列はCSVファイルのセルに格納する.

  • CSVに保存する
  • CSVから読み込んでオブジェクトを初期化
  • クラスの構造は未知としてライブラリ化

作戦は,クラスオブジェクトをJSON化して,JSONをCSVに変換するだけ. JSONとCSVの相互変換はこれを使う. 1つのオブジェクトがCSVファイルの各データ行になる.

ライブラリとかありそうなもんだけど見つけられなかったので作った. もっとシンプルに作れるんじゃないかと思うけどとりあえず鈍くても動けばいい.

想定するクラスの階層構造例

クラスオブジェクトからJSONに変換するにはクラスの定義箇所に[Serializable]を追加すればいいらしい. publicの変数でないとシリアライズされずに無視されるので注意が必要.

[Serializable]
public class Test3{
    public int c, d;
    public Test3(){
        c = 2;
        d = 3;
    }
}
[Serializable]
public class Test2{
    public int a, b;
    public Test3 c;
    public Test2(){
        a = 1;
        b = 2;
        c = new Test3();
    }
}
[Serializable]
public class Test{
    public string a;
    public Test2 b;
    public Test(){
        a = "aho";
        b = new Test2();
    }
}

使い方


# オブジェクトからCSV  ------------------------------------------

#インスタンスを作成
Test obj = new Test();

#オブジェクトをJSONに変換
string json_txt = JsonUtility.ToJson(obj);

#JSONからCSVのヘッダとデータ1行に変換
string csv_header = JsonCsv.JsonToCsvHeader(json_txt);
string csv_row = JsonCsv.JsonToCsvRow(json_txt);


# CSVからオブジェクト ------------------------------------------

#CSVヘッダからDictionary<string, object>に変換
var dict = JsonCsv.CsvHeaderToDict(csv_header+'\n');

#Dictionary<string, object>からJSONに変換
string json_csv = JsonCsv.CsvRowToJson(dict, csv_row+'\n');
Console.WriteLine(json_csv);

#JSONをTestクラスのオブジェクトに変換
Test obj_out = JsonUtility.FromJson<Test>(json_out);

#値を確認
Console.WriteLine(obj_out.b.a + 1);

obj_out.b.aを出力したのはこの変数がint型の整数だったから. JSONのデータでは"1"というダブルクォーテーションで囲まれた文字列扱いだけどちゃんとメンバ変数の型に合わせて変換してくれたみたい.

#a,b:a,b:b,b:c:c,b:c:d
aho,1,2,2,3
{"a":"aho","b":{"a":"1","b":"2","c":{"c":"2","d":"3"}}}
2

参考文献