2011-08-09 12 views
15

JSONオブジェクトのプロパティに基づいてJSON.NETを使用して型の解決をオーバーライドできますか?既存のAPIに基づいて、JsonPropertyCollectionを受け入れてTypeを返す方法が必要なようです。JSON.NETのプロパティベースの型解決

注:私はTypeNameHandling attributeを認識していますが、これは$typeプロパティを追加します。私はソースJSONを制御できません。

答えて

14

これは、カスタムJsonConverterを作成し、それをデシリアライズする前にJsonSerializerSettings.Convertersに追加することによって処理されるようです。

nonplusは、CodeplexのJSON.NET discussions boardに便利なサンプルを残しました。カスタムTypeを返すようにサンプルを修正し、その場所にオブジェクトインスタンスを作成するのではなく、デフォルトの作成メカニズムを延期しました。

abstract class JsonCreationConverter<T> : JsonConverter 
{ 
    /// <summary> 
    /// Create an instance of objectType, based properties in the JSON object 
    /// </summary> 
    protected abstract Type GetType(Type objectType, JObject jObject); 

    public override bool CanConvert(Type objectType) 
    { 
     return typeof(T).IsAssignableFrom(objectType); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, 
     object existingValue, JsonSerializer serializer) 
    { 
     JObject jObject = JObject.Load(reader); 

     Type targetType = GetType(objectType, jObject); 

     // TODO: Change this to the Json.Net-built-in way of creating instances 
     object target = Activator.CreateInstance(targetType); 

     serializer.Populate(jObject.CreateReader(), target); 

     return target; 
    } 
} 

そして、ここで使用例(前述したようにも更新)です:

class VehicleConverter : JsonCreationConverter<Vehicle> 
{ 
    protected override Type GetType(Type objectType, JObject jObject) 
    { 
     var type = (string)jObject.Property("Type"); 
     switch (type) 
     { 
      case "Car": 
       return typeof(Car); 
      case "Bike": 
       return typeof(Bike); 
     } 

     throw new ApplicationException(String.Format(
      "The given vehicle type {0} is not supported!", type)); 
    } 
} 
+0

何実装されていない抽象 'WriteJson'方法は? –

+1

@CanPoyrazoğluCanWriteプロパティをオーバーライドしてfalseに設定すると便利です。これにより、コンバータはデフォルトの動作に戻ります。 – bmeredith

関連する問題