.NET (C#) で複数オブジェクトをストリームに JSON シリアライズ
公開:
更新:
BinaryFormatter
が将来的に .NET から削除されるようです(つい最近まで知らなかった勢)。
Python の pickle
同様、低レイヤ API としてあくまでリスクがあっても使えるようにしてあるし、これからもそうであろうと思っていたので驚きました。
破壊的変更:BinaryFormatter シリアル化メソッドが古い形式になり、ASP.NET アプリでは使用不可に - .NET
Core .NET ライブラリにおける .NET 5 の破壊的変更について学習します。BinaryFormatter、Formatter、および IFormatter におけるシリアル化と逆シリアル化メソッドが古いものになりました。
JsonSerializer
へ移行すれば良さそうですが、一つのストリームに対して一つのオブジェクトしか保存できず、BinaryFormatter
で出来ていた複数オブジェクトを一つのファイルへ書き込むような API が存在しません。
JsonSerializer クラス (System.Text.Json)
オブジェクトまたは値型を JSON にシリアル化したり、JSON をオブジェクトまたは値型に逆シリアル化したりする機能を提供します。
Unity でセーブデータ保存に BinaryFormatter
を利用しており、複数オブジェクトを同一ファイルに何も考えず入れていたので、対処法を考えました。
実装
あまりにも普通 (trivial) すぎる方法ですが、ペイロードサイズとペイロードを交互に書き込む実装としました。JsonUtility
は UnityEngine
から使える JSON シリアライザです(System.Text.Json
のものではないです)。
シリアライズ
using (var fs = new FileStream(saveFilePath, FileMode.Create, FileAccess.Write))
{
var jsonString = JsonUtility.ToJson(saveData);
var data = Encoding.UTF8.GetBytes(jsonString);
fs.Write(data, 0, data.Length);
}
デシリアライズ
using (var fs = new FileStream(saveFilePath, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
var jsonString = Encoding.UTF8.GetString(bytes);
saveData = JsonUtility.FromJson<JsonSaveData>(jsonString);
}