2016-06-13 40 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

相關問題