2017-08-07 23 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

相关问题