2012-10-09 62 views
1

我的問題是,當轉換器應用於接口的實現時,我的JsonConverter似乎沒有被json.net反序列化過程調用,而propertytype是接口。 我使用TypeNameHandling = TypeNameHandling.Objects將$ type添加到json中。我在序列化和反序列化兩方面都這樣做。 當我有一個屬性是一個接口的實現類的轉換器正確調用。 但是,當我有一個接口類型的屬性,具體類的轉換器不會被調用。Json.net反序列化接口,具體類使用JsonConverter

當我反序列化這個類時,我的JsonDataBagCreationConverter將由RealTelephone調用,但不是由電話調用,因爲這是一個接口。 儘管它們都使用正確的$類型進行了序列化。 這會導致RealTelephone的.Data被填充,而Telephones .Data爲空。

[JsonConverter(typeof(JsonDataBagCreationConverter<ContainerForITelephone>))] 
public class ContainerForITelephone : IDataBag 
{ 
    private object _data; 
    private DataBagTypeEnum _dataBagTypeEnum; 
    public ITelephone Telephone { get; set; } 
    public Telephone RealTelephone { get; set; } 

    public object Data 
    { 
     get { return _data; } 
     set { _data = value; } 
    } 

    public DataBagTypeEnum DataBagType_Enum 
    { 
     get { return _dataBagTypeEnum; } 
    } 
} 

此jsonconverter未被調用的電話屬性。但它適用於RealTelephone。

public class JsonDataBagCreationConverter<T> : JsonConverter where T : IDataBag, new() 
{  
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    {   
     if (reader.TokenType != JsonToken.Null) 
     { 
      var jsonObject = JObject.Load(reader); 
      var target = Create(objectType, jsonObject); 
      serializer.Populate(jsonObject.CreateReader(), target); 
      ((IDataBag)target).Data = jsonObject.ToString(); 
      return target; 
     } 
     return null; 
    } 

}

[JsonConverter(typeof(JsonDataBagCreationConverter<Telephone>))] 
public class Telephone : ITelephone 
{ 
    public string Name { get; set; } 
    public string AreaCode { get; set; } 
    public string Number { get; set; } 
    public SubPhone SubPhone { get; set; } 

    public object Data { get; set; } 
    public DataBagTypeEnum DataBagType_Enum { get; set; } 
} 

我期待着您的來信,感謝

回答

0

解決:

public class JsonDataBagCreationConverter<T> : JsonConverter where T:IDataBag 
{ 

//, new() prevented us from using interfaces. Activator.CreateInstance did the trick in Create 

//Used when the object decorated with [JsonConverter(typeof(JsonDataBagCreationConverter<xxxx>))] is de-serialized 
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
var jsonObject = JObject.Load(reader); 

     if (objectType.IsInterface) 
     { 
      // Interfaces cannot be instantiated but must be converted to their "real" implemented type 
      // Because we serialize with settings.TypeNameHandling = TypeNameHandling.Objects; 
      // A $type property is added to the json by the deserializer. 
      string type = jsonObject["$type"].ToString(); 
      var typesAsArray = type.Split(','); 
      var wrappedTarget = Activator.CreateInstance(typesAsArray[1], typesAsArray[0]); 
      var realTarget = wrappedTarget.Unwrap() as IDataBag; 
      serializer.Populate(jsonObject.CreateReader(), realTarget); // Will call this function recursively for any objects that have JsonDataBagCreationConverter as attribute 
      ((IDataBag)realTarget).Data = jsonObject.ToString(); // This is where custom data is stored in databag 
      return realTarget; 
     } 

     // Non interface 
     var target = Create(objectType, jsonObject); 
     serializer.Populate(jsonObject.CreateReader(), target); // Will call this function recursively for any objects that have JsonDataBagCreationConverter as attribute 
     ((IDataBag)target).Data = jsonObject.ToString(); // This is where custom data is stored in databag 
     return target; 


} 

public override bool CanRead 
{ 
    get 
    { 
     return true; 
    } 
} 

public override bool CanWrite 
{ 
    get 
    { 
     return false; 
    } 
} 

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
{ 
    throw new Exception("WriteJson not implemented"); 
} 

protected IDataBag Create(Type objectType, JObject jsonObject) 
{ 
    var aa = Activator.CreateInstance(objectType); 
    return aa as IDataBag; 
    // return new T(); // this demands ,new() on the class and then it will not work with interfaces 
} 

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

}