2013-03-14 44 views
3

我有麻煩反序列化我的對象。它包含以下屬性:JSON.NET:反序列化一個類包含一個從接口派生的對象列表

public List<IShape> Shapes { get; set; }; 

和JSON.NET反序列化器總是告訴我,它不可能實例化一個接口。

我有幾個類實現接口,實現IShape接口,例如Polyline -> IPolyline -> IShape。我嘗試了兩種解決方案已經:

但我得到了同樣的例外,那IShape的不能instantied,被拋出。

我用TypeNameHandling.AutoTypeNameHandling.All序列化對象也沒有幫助,甚至當我使用上面鏈接的帖子中提到的轉換器。

有沒有人知道這個問題的解決方案?如果需要某些代碼,我會很樂意發佈它。

以下是生成的JSON示例。

"$type": "SketchModel.Layer, SketchModel", 
     "Id": 57865477, 
     "Shapes": { 
      "$type": "System.Collections.Generic.List`1[[SketchModel.Shapes.AbstractShapes.IShape, SketchModel]], mscorlib", 
      "$values": [ 
      { 
       "$type": "SketchModel.Shapes.Polyline, SketchModel", 

這條線負責的問題:

"System.Collections.Generic.List`1[[SketchModel.Shapes.AbstractShapes.IShape, SketchModel]], mscorlib" 

它根本不知道如何實例IShape的。如果我創建一個自定義轉換器並讓它爲每個IShape返回一條Polyline,它就可以工作,但不會創建任何其他形狀(例如橢圓)。

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)方法,在自定義轉換器重寫,如果我讓我打印的objectType的完整類型名稱,它總是IShape的,從來沒有別的......

+0

的可能重複[JSON.NET - ?如何反序列化接口的實例集合(http://stackoverflow.com/questions/15880574/json-net-how-to-deserialize-collection-of-interface-實例) – nawfal 2014-07-20 12:02:57

回答

2

唯一的例外是有道理的,因爲沒有按解串器不知道接口在保溼時應該代表什麼具體類型。

在序列化期間,JSON.NET允許你配置它來添加一些元數據在這種情況下使用。 This SO question有一個解釋如何配置它的答案。

該配置將爲將在反序列化期間使用的JSON添加一個type屬性。

+0

我已經序列化與TypeNameHandling.AUTO對象,TypeNameHandling.ALL都於事無補,不知爲什麼就不能正確地提取信息。 – 2013-03-14 12:19:44

+0

您是否嘗試過TypeNameHandling.Objects? – 2013-03-14 13:25:02

+0

是的,結果相同。 – 2013-03-14 13:30:44

0

我完全是這個問題,只有通過明確提供一個類型的轉換器來解決它。

state = JsonConvert.DeserializeObject<StateImpl>((String)stateObject, new JsonConverter[] { new StatePersistenceStateEntryConverter(), new StatePersistenceUserInteractionConverter() }); 

凡我StateImpl對象包括這些屬性:

[DataMember] 
    [JsonProperty("stateEntries", TypeNameHandling = TypeNameHandling.Auto)] 
    public List<IStateEntry> StateEntries 
    { 
     get; 
     set; 
    } 

    [DataMember] 
    [JsonProperty("precommitStateEntry", TypeNameHandling = TypeNameHandling.Auto)] 
    public IPrecommitStateEntry PrecommitStateEntry 
    { 
     get; 
     set; 
    } 

IPrecommitStateEntry擴展IStateEntry - 我需要通過轉換器在反序列化 - 基本上是這樣的,如果我使用的標註它不工作接口(只是供參考,如果你想知道爲什麼在轉換器中額外的邏輯)。

而且 - 在我IStateEntry對象,我有一個類似的問題兒童:

[DataMember] 
    [JsonProperty("userInteractions", TypeNameHandling = TypeNameHandling.Auto)] 
    public List<IUserInteraction> UserInteractions 
    { 
     get; 
     set; 
    } 

所以我的對象有IStateEntry的孩子列表屬性和IStateEntry具有IUserInteraction的另一子列表。我的轉換器如下:

public class StatePersistenceStateEntryConverter : CustomCreationConverter<IStateEntry> 
{ 
    public override IStateEntry Create(Type objectType) 
    { 
     if (objectType == typeof(IPrecommitStateEntry)) 
     { 
      return new PrecommitStateEntry(); 
     } 
     else 
     { 
      return new StateEntry(); 
     } 
    } 
} 

而且......

public class StatePersistenceUserInteractionConverter : CustomCreationConverter<IUserInteraction> 
{ 
    public override IUserInteraction Create(Type objectType) 
    { 
     return new UserInteraction(); 
    } 
} 

字面上所有他們正在做的是創建一個特定對象實現的實例。

所以我不知道爲什麼轉換器系統所需要的顯然是一個列表可以被實例化 - 只是沒有單獨的IStateEntry。很顯然,NewtonSoft實現中存在一個錯誤 - 或者我錯過了一些基本的東西。

希望有所幫助。對我來說這是一個令人沮喪的時間,但現在工作了!

相關問題