Root name がdynamicなjson ?ルートネームが動的なjson ?(なんと表現するのが正しいのでしょうか...)
以下のようなjsonをデシリアライズするときのお話です。
"araragi koyomi"と"oshino meme"の部分が動的に変わっていくケースを想定しています。
動的な名前の下には、userId、name、ageとfamilyを並べました。familyは、Personの配列です。
(familyの中のpersonにfamilyがないとかは...サンプルなので書いてないだけです)。
> Environment
- Visual Studio 2015 update3
- Json.NET 9.0.1
> 事前準備
jsonをデシリアライズするPersonのモデルを以下のようにしました。
では、jsonのファイルを読み込んでデシリアライズするという流れをいくつかのパターンで実装していきます。
その1 - 地味にこねこね...
ファイルを読み込んで、JObjectにパースし、そこからList
listをnewするコードなんて書きたくないし、LINQ使えよって突っ込みたくなるので...以下のようにちょっとだけ修正しました。
その2 - JsonConverterを使ってデシリアライズ
JsonConverter
を使ってパースの処理を抜き出しちゃいます。
Person
クラスをデシリアライズするためのJsonConverter
を継承した、PersonsConverter
クラスを作ります。
使い方は、以下です。地味にこねこね時代のコードに比べると、まーすっきりします。
var persons = JsonConvert.DeserializeObject<List<Person>>(json, new PersonsConverter());
その3 - JsonConverterを使ってデシリアライズ+α
もうちょっと実用的な使い方として思いつくのは、Attributeにつけるパターンです(ケースバイケースですけど)。
まず、ListJsonConverter
のAttributeをつけます。Attributeで指定している型、PersonsModelConverter
クラスはこの後作ります。
次は、PersonsModelConverter
クラスを書きましょう。「その1」で作ったPersonsConverter
ちょっと変更するだけです。
PersonsConverter
ではListPersonsModel
を出力するよう変えただけです(14行目あたり)。
結果として、PersonsModel
クラスは、AttributeでPersonsModelConverterを使うように指定しているため、実際にデシリアライズする使うときは以下のコードになります。もはや、普通にJsonConvert.DeserializeObjectしているだけとなります。
var personsModel = JsonConvert.DeserializeObject<PersonsModel>(json);
ModelのBehaviourをModelに依存させているという点で、ビジネスロジックに絡むところをすっきりさせれたといえますかね(個人的主観です)。
おしまい。