2016-08-19 71 views
3

我有2个班这样

class A: Base 
{ 
    public string CommonField; 
    public int IntField; 
} 

class B: Base 
{ 
    public string CommonField; 
    public double DoubleField; 
} 

我序列A实例与类型名处理

{ 
    "$type": "MyApp.A, MyApp", 
    "CommonField": "SomeValue", 
    "IntField": 123, 
    "SomeBaseField": 321 
} 

什么是从此得到B实例的最简单的方法?在问你为什么之前,它是关于导入A作为B(它们具有基本属性和那些名称与你所看到的匹配,所以这个操作是合理的)。

尝试反序列化给JSON作为B将抛出

Newtonsoft.Json.JsonSerializationException: Type specified in JSON 'MyApp.A, MyApp, Version=0.0.1.1, Culture=neutral, PublicKeyToken=null' is not compatible with 'MyApp.B, MyApp, Version=0.0.1.1, Culture=neutral, PublicKeyToken=null'. Path '$type', line 2, position 42. 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolveTypeName(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, String qualifiedTypeName) 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id) 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) 

我能想到以下几点:

  1. 反序列化JSON作为A,创建B实例并复制所有值(坏) ;
  2. 替换(甚至可以删除?)$type在json中,并尝试将其反序列化为B(更好,仍然不好);
  3. 使用SerializationBinder和反序列化JSON作为B(好)


public class JsonABBinder : DefaultSerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     if (typeName == "MyApp.A") 
      return typeof(B); 
     return base.BindToType(assemblyName, typeName); 
    } 
} 

有没有更好的办法?在我的场景中,有许多这样的类型,并且有这样的绑定器被人追捕(以及首先阅读json,以确定应用哪个绑定)是非常乏味的。

我正在寻找一种简单的方法来忽略$type并直接指定想要的类型(泛型方法),因为我知道类型我需要,但我不知道哪种类型是在json中,我想忽略它。

回答

3

您可以使用:

new JsonSerializer().TypeNameHandling = TypeNameHandling.None 

这将忽略$类型。

+0

这是非常美丽和简单,谢谢。 – Sinatr

2

这将是deseralizing类型时,在一些设置来传递一个好主意:

private readonly JsonSerializerSettings _settings = new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.None 
}; 

然后使用它像:

var json = JsonConvert.DeserializeObject<object>(jsonString, _settings); 

或者也可以简单

var json = JsonConvert.DeserializeObject<object>(jsonString, new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.None 
}); 
相关问题