如何在反序列化期间忽略$ type

时间:2016-08-19 09:50:27

标签: c# json.net

我有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. 在json中替换(甚至删除?)$type并尝试将其反序列化为B (更好,仍然不好);
  3. 使用SerializationBinder并将json反序列化为B (好)

  4. 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为A以确定应用哪个绑定器)非常繁琐。

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

2 个答案:

答案 0 :(得分:5)

您可以使用:

new JsonSerializer().TypeNameHandling = TypeNameHandling.None

这将忽略$ type。

答案 1 :(得分:4)

在解除类型设置时传递一些设置是个好主意:

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
});