見出し画像

Json.NETでキー名が不定のJSONを読み込む方法

※ この記事は 1年以上前に他のブログに投稿した記事の再構成です。

休日の趣味プログラミングで「デレマスボーダーbot」の「Cinderella API」を利用するWindows アプリを作成したのですが、仕事で使う Web APIのレスポンスは XML形式ばかりで JSON形式の Web APIは初めてだったので色々と試行錯誤した内容を共有したいと思います。

まずは普通に Json.NETを使ってみたが……

仕事で読み込む XMLは情報量が少ないので XDocumentでゴリゴリやってしまうのですが、Cinderella APIは情報量が多いので JSONの読み込みには Json.NETを使用することにしました。Json.NETを使用すれば以下の様なコードだけで Cinderella APIの JSONを読み込めると思ったからです。

// デシリアライズ
var producers = Newtonsoft.Json.JsonConvert.DeserializeObject(json);

しかし、Cinderella APIの JSONはこのコードだけでは例外が発生して読み込むことができませんでした。原因は記事タイトルの通りキー名(下記コードの "272"部分)が不定だったためです。

// プロデューサー明細情報
{
    // イベント毎に変わるキー名
    "272": { 
    "eventEndDateTime": "2019-04-08T14:00:00Z",
    ~ 中略 ~
    "eventName": "花見DEドリームLIVEフェスティバル"
    },
    ~ 以下、イベント毎のオブジェクト配列 ~
},

キー名が不定な場合の読み込み方法

付け焼き刃ながら Json.NETについて調べた結果、次の手順で Cinderella APIの JSONを読み込めるようになりました。今回はプロデューサー明細情報の APIを例に紹介します。

手順 1: プロデューサー明細情報のクラスを作成

まずは JSONの内容を格納するプロデューサー明細情報のクラスを作成します。

// プロデューサー明細情報
public class Producer
{
    public int eventDetailId { get; set; }     // イベント明細ID(キー)
    public string eventName { get; set; }      // イベント名
    ~ 中略 ~
    public string favorite3Hash { get; set; }  // ホシイモノ3カードハッシュ
    public string favorite3Name { get; set; }  // ホシイモノ3カード名
}

手順 2: プロデューサー明細情報のリストを格納するクラスを作成

次に プロデューサー明細情報のリストを格納するクラスを作成します。JsonConverter属性に指定しているクラスは次のステップで作成します。

// プロデューサー明細情報 モデル
[Newtonsoft.Json.JsonConverter(typeof(ProducersModelConverter))]
class ProducersModel
{
    public List<Producer> Producers { get; set; }
}

手順 3: JsonConverterを継承して ReadJsonをオーバーライド

次に手順2で属性に記述した JsonConverterを継承したクラスを作成します。ここで不定なキー名の処理を行います。

// プロデューサー明細情報 コンバーター
public class ProducersModelConverter : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType) => objectType == typeof(List<Producer>);

    public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
    {
        var producers = serializer.Deserialize<JObject>(reader).Properties().Select(p =>
        {
            // 値をオブジェクトに変換
            var producer = p.Value.ToObject<Producer>();
            // 必要に応じて不定なキー名を処理
            producer.eventDetailId = int.Parse(p.Name);

            return producer;
        }).ToList();

        return new ProducersModel() { Producers = producers };
    }
    ~ 以下略 ~
}

手順 4: Cinderella APIの JSONを読み込む

これまでに作成したクラスを Json.NETに渡して Cinderella APIの JSONをデシリアライズしてもらいます。

// デシリアライズ
var producers = Newtonsoft.Json.JsonConvert.DeserializeObject<ProducersModel>(json);

参考にした記事: 

以上の手順で何とか Cinderella APIのプロデューサー明細情報の JSONを読み込むことができました。Cinderella APIのイベント情報などは更にネストしていてもう少し工夫が必要になりますが基本的な考え方は変わりません。JSON形式を扱うこと自体が初めてなのでこれが最適解かはわかりませんが参考になれば幸いです。

見出し画像: フリー写真素材ぱくたそ

この記事が気に入ったらサポートをしてみませんか?