C#のList<T>をJSON形式でシリアライズ・デシリアライズする。

C# コンピュータ
C#

List<T>のTをインターフェースにしたオブジェクトをJSON形式でシリアライズ・デシリアライズ出来るのか確認してみます。
予想ですがシリアライズは出来てもデシリアライズは無理そうな気がします。

まずはシリアライズしてみます。

using System.Text;
using System.Text.Json;

interface ISampleBase
{
    public string ClassName { get; set; }
}

class SampleClassTypeA : ISampleBase
{
    public string ClassName { get; set; } = "SampleClassTypeA";
}

class SampleClassTypeB : ISampleBase
{
    public string ClassName { get; set; } = "SampleClassTypeB";
}

class Program
{
    static void Main()
    {
        string path = @".\sample.json";
        
        List<ISampleBase> sampleList = new( [new SampleClassTypeA(), new SampleClassTypeB(),] );

        // シリアライズ
        var jsonStr = JsonSerializer.Serialize(sampleList);

        // エンコードを指定して保存
        var encoding = Encoding.GetEncoding("utf-8");
        using( var writer = new StreamWriter(path, false, encoding))
        {
            writer.WriteLine(jsonStr);
        }     
    }
}

実行した結果sample.jsonの中身は以下の様になりました。

[{"ClassName":"SampleClassTypeA"},{"ClassName":"SampleClassTypeB"}]

クラス名が見えますがこちらは意図的にプロパティにセットした文字列です。見た感じインターフェイスをで見えるプロパティを
そのままJSON化しているようです。

期待薄ですが続けてでシリアライズをしてみます。

        string path2 = @".\sample.json";
        // エンコードを指定して読み込み
        var jsonStr2 = "";
        var encoding2 = Encoding.GetEncoding("utf-8");
        using( var reader = new StreamReader(path2, encoding2))
        {
            jsonStr2 = reader.ReadToEnd();
        }

        // デシリアライズ
        var loadObj = JsonSerializer.Deserialize<List<ISampleBase>>(jsonStr);

        // タイプを取得
        var type = loadObj?.GetType();

        Debug.Print($"{type}");

実行したところデシリアライズで以下のようなエラーが発生しました。
System.NotSupportedException : Deserialization of interface types is not supported. Type ‘ISampleBase’.

ISampleBaseインターフェースの部分をSampleClassTypeAへ置き換えてみます。

        // デシリアライズ
        var loadObj = JsonSerializer.Deserialize<List<SampleClassTypeA>>(jsonStr);

実行したところエラーは発生しませんでした。

System.Collections.Generic.List`1[SampleClassTypeA]

インターフィエスのままシリアライズは出来ても、デシリアライズで実体化することは出来ませんでした。

派生クラスで生成したオブジェクトの情報も含んでシリアライズしてくれることを期待しましたが、残念ながらそのようにはなっていないようです。何か解決方法があるのかもしれませんが、List<T>を使うのをやめるか自前でシリアライズするコードを書くなど、別な方法を模索してみたいと思います。

コメント