概要
C#アプリで設定情報を設定ファイルに書き出し⇔読み出しするためにシリアライズするところで盛大にはまったので、結果を遺しておきます
コード
シリアライザ
/// <summary>
/// シリアライズ・デシリアライズをするクラス
/// </summary>
/// <typeparam name="T">対象クラス</typeparam>
class Serializer<T>
{
/// <summary>
/// オブジェクトをUTF-8のjsonファイルにシリアライズする。
/// </summary>
/// <param name="obj">対象オブジェクト。要件1=POCOであること。要件2=シリアライズ対象メンバがpublicでgetter/setterがついていること</param>
/// <param name="filePath">シリアライズ先のファイルパス。既存の場合は上書きされる。</param>
public static void jsonSerializeUtf8(T obj, string filePath)
{
var options = new System.Text.Json.JsonSerializerOptions
{
// trueだと出力を整形する
WriteIndented = true,
// UNICODEエスケープシーケンスにしない対象を指定。やらないと、ASCII文字以外すべてが あ → \u3042 みたいな感じでエスケープされる。
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All),
};
byte[] jsonOutput = System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(obj, options);
System.IO.File.WriteAllText(filePath, System.Text.Encoding.UTF8.GetString(jsonOutput));
}
/// <summary>
/// シリアライズされたUTF-8のjsonファイルから、オブジェクトを復元する。
/// </summary>
/// <param name="filePath">シリアライズされたファイルのパス。</param>
/// <returns>復元されたオブジェクト</returns>
public static T jsonDeserializeUtf8(string filePath)
{
byte[] jsonInput = System.IO.File.ReadAllBytes(filePath);
var utf8Reader = new System.Text.Json.Utf8JsonReader(jsonInput);
return System.Text.Json.JsonSerializer.Deserialize<T>(ref utf8Reader);
}
}
usingなしで動くように書いたので若干もっさいです。
手段がjsonであることについて
設定ファイルの選択肢としてはapp.configあたりがあったり、他のシリアライズ手段としてはxmlシリアライズあたりがありますが、
・app.configはkey-value式なので複雑な構造はめんどくさい
・xmlシリアライズはLISTの格納時に色々めんどくさいっぽい
あたりでjsonに絞りました。
実際、コード内の public static void jsonSerializeUtf8
のコメントに書いた通り、POCOかつgetter/setter付きにすれば問題なく動いてくれています。
ポエムな背景
設定ファイルを読み書きしたい
→App.config ・・・xmlで定義しないとだめっぽい?しかもkey-valueだけ?
→xml・・・Listが入るとうまくいかない。サンプルコードによると保存時にコードに特別な処理が必要?やってられん
→json・・・公式の記事からするとこれが最新の手段だから楽になってくれてるかもしれない・・・頼む・・・→いけた