2016-06-13 39 views
0

我从json格式的服务接收到一些数据。部分数据是BASE类的对象(比如说)。有许多类从它派生出来: enter image description here不使用程序集名称反序列化多态类型,只用Newtonsoft lib

现在服务器发送一个固定的结构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库反序列化的内容。正如你所看到的,服务器发送从BASE类派生的每个对象的$ type信息,我希望能够在客户端反序列化过程中将这些对象加载到它们各自的类型中。我deserliaze的JSON转换成类型响应

class Response 
{ 
    string Status; 
    BASE object1; 
    BASE object2; 
} 

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

的目标正如你所看到的,我不指定对象B1或A3或B2的确切类型,在响应对象,我想Newtonsoft LIB给init object1和object2,并在json消息中使用基于$ type值的适当类型。

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

我知道我可以通过定义一个定制绑定(从SerializationBinder派生类),并重写BindToName和BindToType性质(refer link

实现这一点,但问题是,我们不希望使用JSON。来自System.Runtime.Serialization的Net SerializationBinder。我们的模块只能使用Newtonsoft lib。任何解决方案?

+1

您可以按照[使用json.net反序列化多态json类的类型](https://stackoverflow.com/questions/19307752)的方式为'Base'创建一个自定义'JsonConverter'。尽管在这种情况下,你确实有类型信息,但你可以在转换器中按照答案的方式手动处理它。 – dbc

+0

我收到的json非常大,两个Base类型的对象只是它的一部分。难道你不认为如果我通过自定义的JsonConverter去编写太多的代码。我也必须序列化它。这不是太多的代码吗? – Rajat

+0

'JsonConverter'将用于'Base'及其抽象子类。你需要做的就是维护一个从类型名到类型的查找字典。 JSON的整体大小是不相关的,其他类的数量无关紧要。当然,编写自己的'SerializationBinder'会更容易,也就是解决这个问题的预期方式 - 但无论出于何种原因你不想这样做。 – dbc

回答

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

同样地,我得写自定义的WriteJson方法JsonConverter 。这是你的意思dbc?

如果是的,我有几个问题:

  1. performent这是如何的代码? JObject.Load(阅读器)对于每个调用来说都很昂贵?
  2. 如果BASE类型的对象嵌套在json的深处,它能正常工作吗?
+0

1)您将不得不[自己测试](https://ericlippert.com/2012/12/17/performance-rant/)。 2)是的,BASE对象的嵌套深度并不重要。如果您遇到了一些问题,可以使用详细信息更新您的问题。 – dbc

+0

运作良好。我列出了开关盒中的所有子类型并返回它们的对象。但是,WriteJson呢?我希望能够将这个对象序列化回一个字符串,其中$ type属性被保存为多态类型。 如何编写WriteJson,使其仅适用于多态类型,它也会在Json中编写$ type属性。 “{”状态“:”成功“,”A“:{”$ type“:”A3“,”name“:”Jon“},”B“:{”$ type“:”B2“ ID“:”A34J“}}” – Rajat

+0

感谢dbc,它工作完美。 – Rajat

相关问题