不使用程序集名称反序列化多态类型,只使用Newtonsoft lib

时间:2016-06-13 10:44:11

标签: json json.net deserialization

我从json格式的服务中收到一些数据。数据的一部分是BASE类的对象(比方说)。有许多类派生自它: enter image description here

现在服务器发送一个固定的结构json,并且BASE类型的对象就在其中。我在此处列出的一些示例回复:

"{"Status":"Success","B":{"$type":"B1","id":"123"},"C":null}"

"{"Status":"Success","A":{"$type":"A3","name":"Jon"},"B":{"$type":"B2","id":"A34J"}}"

我在客户端模型中定义了相同的类层次结构,我使用NewtonSoft Json Library来反序列化内容。如您所见,服务器正在发送从BASE类派生的每个对象的$类型信息,我希望能够在客户端反序列化期间将这些对象加载到它们各自的类型中。我将json deserliaze为Response

类型的对象
class Response
{
   string Status;
   BASE object1;
   BASE object2;
}

Response resp = JsonConvert.DeserializeObject<Response>( jsonServiceMsg, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Binder = mycustombinder });

正如您所看到的,我没有指定对象B1或A3或B2的确切类型,在Response对象中,我希望Newtonsoft lib初始化object1和object2,并且具有基于$ type值的相应类型。 json消息。

  

请注意,服务具有这些类(基本和所有派生)   在不同的命名空间中定义,而我(不同的客户端)   命名空间。但为简单起见,服务不绑定命名空间   通过在序列化为json响应时使用自定义绑定器。

我知道我可以通过定义自定义绑定器(从SerializationBinder派生的类)并覆盖BindToName和BindToType属性(refer link

来实现此目的

但问题是我们不想在System.Runtime.Serialization中使用Json.Net SerializationBinder。我们的模块只能使用Newtonsoft lib。任何解决方案吗?

1 个答案:

答案 0 :(得分:1)

正如dbc建议编写自定义JsonConverter一样,使用here

我认为它会像这样:

public override object ReadJson(JsonReader reader, 
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        switch (item[$type].Value<string>())
        {
            case "B1":
                return item.ToObject<B1>();
            case "B2":
                return item.ToObject<B2>();
            case "C1":
                return item.ToObject<C1>();
            case "A1":
                return item.ToObject<A1>();
            case "A2":
                return item.ToObject<A2>();
            case "A3":
                return item.ToObject<A3>();
        }
    }

类似地,我将不得不编写自定义JsonConverter的WriteJson方法。那是什么意思dbc?

如果是,我几乎没有问题:

  1. 这段代码的执行情况如何?每次通话时,JObject.Load(读卡器)似乎都很贵?
  2. 如果BASE类型对象嵌套在json内部,它会正常工作吗?