System.Text.Jsonで苦しんだこと


背景

nugetパッケージのSystem.Text.Jsonにおいて、JsonSerializer.Deserialize()を使う際に苦しんだことをメモしておきます。
メモしないと何度もハマりそうですから。

問題

まとめると、苦しんだこととはjsonをデシリアライズするときの、デシリアライズ先クラスの書きかたでした。
今回は下記3点を知らずに苦しみました。

  1. フィールドにgetter/setterを書く
  2. フィールドの型にDictionaryを使うケース
  3. フィールドの型にListを使うケース

解決策

*サンプルは動作確認していません。

1. フィールドにgetter/setterを書く

具体的に言うと、フィールドは下記のサンプル正のような書きかたをしなければなりません。
要するに、getter/setterで書かなければなりません。
これを見落としたせいで、何度もnull参照エラーを出してしまいました。

誤.cs
    public class Sample
    {
        public string text;
    }
正.cs
    public class Sample
    {
        public string text{ get; set; }
    }

2. ケースα : フィールドの型にDictionaryを使う

具体的には、下記AのJson構造の時は、フィールドにDictionary型を使って下記A'のように定義します。

A.json
{
    "item": {
        "1": {
            "value1": 1,
            "value2": 2
        },
        "2": {
            "value1": 1,
            "value2": 2
        }
    }
}
A'.cs
    public class Sample
    {
        public Dictionary<string, Dictionary<string, int>> item { get; set; }
    }

3. ケースβ : フィールドの型にListを使う

具体的には、下記BのJson構造の時は、フィールドにList型を使って下記B'のように定義します。

B.json
{
    "item": [
        {
            "value1": 1,
            "value2": 2
        },
        {
            "value1": 1,
            "value2": 2
        }
    ]
}
B'.cs
    public class Sample
    {
        public List<Dictionary<string, int>> item { get; set; }
    }

【メモ】忘備のための蛇足

ケースβではfirefoxを使って、jsonデータの中身を整形表示したものを見ながら、クラスを書いていました。
下記のごとく、firefoxはケースβのようなjsonに対して、自動でitem直下の要素に対して連番を振ってくれていました。
その連番に惑わされました。
ケースαと同じで行けるだろうと勘違いしていて、Dictionary型で何度も挑戦してハマっていました。
よく見ると違いが判るのですが。

  1. ケースαのfirefox表示

  2. ケースβのfirefox表示

反省

個人的に、今後jsonデータを扱う頻度が増えそうです。
できれば、jsonを今回のnugetパッケージでデシリアライズするとき、jsonデータを入力することでC#クラスファイルを出力するようなツールが欲しいです。
表示するだけのツールでは、目を凝らさなければ今回のような見落としが発生しそうなので、コード書いてくれるようなツールに頼りたいです。
jsonについての基礎知識を身につけることが先かもしれません。