2017-08-07 24 views
1

編輯:澄清問題:如何通過[JsonConverter]調用JsonConvert.DeserializeObject並禁用應用於基本類型的JsonConverter?

我已經覆蓋了JsonConverter爲基本類型(應用[JsonConverter(typeof(TConverter))]超類),而是直接反序列化分型時,我想使用標準序列(即沒有自定義轉換器),用於反序列化我的派生對象。如何在反序列化方法中指定STANDARD序列化,就像我沒有重寫JsonConverter一樣?

我正在使用彈性搜索,並且無法使用JsonConverter的自定義實現調用JsonConvert.DeserializeObject,並且必須依賴Elastic的屬性來使用我的轉換器。

但是,使用此轉換器作爲屬性似乎也會影響所有子類,但我只是希望他們使用標準轉換器,這樣我就不必爲許多實現中的每一個實現JsonConverter。

這是我的課/邏輯,因爲我想它看起來:

[Route("test")] 
    [HttpPost] 
    public HttpResponseMessage Test([FromBody] JToken json) 
    { 
     var res = json.ToObject<Product>(); // I want an object of ProductImpl type here 
     return Request.CreateResponse(res); 
    } 

    [JsonConverter(typeof(JsonProductConverted))] 
    public abstract class Product 
    { 
    } 

    public class ProductImpl : Product 
    { 
    } 

    public class JsonProductConverted : JsonConverter 
    { 
     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      JObject json = JObject.Load(reader); 
      //var type = GetTypeFromId((int) json["typeId"]); // Construct type from field in 
      var type = typeof(ProductImpl); 
      // var res = JsonConvert.DeserializeObject(json.ToString(), type, DEFAULT_JSONCONVERTER_HERE); 
      var res = DeserializeToObjectWithStandardJsonConverter(json, type); 
      return res; 
     } 

     public override bool CanConvert(Type objectType) 
     { 
      return false; 
     } 
    } 

如果我不提供默認JsonConverter,或類似它只會使用JsonProductConverted轉換器,它創建了一個無限循環。

+0

請嘗試制定一個明確的問題,很難得到你所要求的。 – Mafii

回答

1

既然你已經直接添加[JsonConverter(typeof(JsonProductConverted))]Product類型,你可以虛擬轉換器從CanReadCanWrite添加到ProductImpl返回false

[JsonConverter(typeof(NoConverter))] 
public class ProductImpl : Product 
{ 
} 

public class NoConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return false; 
    } 

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

樣品.Net fiddle

另一種選擇是使用serializer.Populate()。這避免了針對物體本身的轉換器的呼叫:

public class JsonProductConverted : JsonTypeInferringConverterBase 
{ 
    protected override Type InferType(Type objectType, JObject json) 
    { 
     //var type = GetTypeFromId((int) json["typeId"]); // Construct type from field in 
     return typeof(ProductImpl); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return false; 
    } 
} 

public abstract class JsonTypeInferringConverterBase : JsonConverter 
{ 
    public override bool CanWrite { get { return false; } } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    protected abstract Type InferType(Type objectType, JObject json); 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var json = JObject.Load(reader); 

     var actualType = InferType(objectType, json); 

     // Construct object (or reuse existingValue if compatible) 
     if (existingValue == null || !actualType.IsAssignableFrom(existingValue.GetType())) 
     { 
      var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(actualType); 
      existingValue = contract.DefaultCreator(); 
     } 

     // Populate object. 
     using (var subReader = json.CreateReader()) 
     { 
      serializer.Populate(subReader, existingValue); 
     } 

     return existingValue; 
    } 
} 

樣本fiddle #2

+0

這工作100%。允許在Elastic Search中保存抽象類,然後非常容易地將它們反序列化爲實際對象,並且即使對於具有大量實現的抽象對象也可以非常簡單。 非常感謝。 – Nixxon

+0

這是非常棒的,但我需要添加一個私有的json構造函數到我的具體類中,以使它們正確地反序列化。如果得到完整的解釋(或鏈接),那麼合同方面是關於如何使我現有的知識不會延伸到那個,我永遠不會解決這個問題 – m1nkeh

相關問題