2011-08-17 97 views
25

我在使用涉及多態對象數組的JSON反序列化時遇到問題。我已經嘗試了序列化的解決方案,其文檔編號爲herehere,這對於序列化非常有用,但都在反序列化中爆炸。JSON使用多態對象數組進行反序列化

我的類結構如下:

IDable

[DataContract(IsReference=true)] 
public abstract class IDable<T> { 

    [DataMember] 
    public T ID { get; set; } 
} 

觀察組

[DataContract(IsReference=true)] 
[KnownType(typeof(DescriptiveObservation))] 
[KnownType(typeof(NoteObservation))] 
[KnownType(typeof(NumericObservation))] 
[KnownType(typeof(ScoredObservation))] 
public class ObservationGroup : IDable<int> { 

    [DataMember] 
    public string Title { get; set; } 

    [DataMember] 
    public List<Observation> Observations { get; set; } 

    [OnDeserializing] 
    void OnDeserializing(StreamingContext context) 
    { 
     init(); 
    } 

    public ObservationGroup() { 
     init(); 
    } 

    private void init() 
    { 
     Observations = new List<Observation>(); 
     ObservationRecords = new List<ObservationRecord>(); 
    } 

} 

DescriptiveObservation

[DataContract(IsReference = true)] 
public class DescriptiveObservation : Observation 
{ 

    protected override ObservationType GetObservationType() 
    { 
     return ObservationType.Descriptive; 
    } 
} 

NoteObservation

[DataContract(IsReference = true)] 
public class NoteObservation : Observation 
{ 
    protected override ObservationType GetObservationType() 
    { 
     return ObservationType.Note; 
    } 
} 

NumericObservation

[DataContract(IsReference = true)] 
public class NumericObservation : Observation 
{ 
    [DataMember] 
    public double ConstraintMaximum { get; set; } 
    [DataMember] 
    public double ConstraintMinimum { get; set; } 
    [DataMember] 
    public int PrecisionMaximum { get; set; } 
    [DataMember] 
    public int PrecisionMinimum { get; set; } 
    [DataMember] 
    public string UnitType { get; set; } 

    protected override ObservationType GetObservationType() 
    { 
     return ObservationType.Numeric; 
    } 
} 

ScoredObservation

[DataContract(IsReference = true)] 
public class ScoredObservation : Observation { 
    [DataMember] 
    public int Value { get; set; } 

    protected override ObservationType GetObservationType() { 
     return ObservationType.Scored; 
    } 
} 

我公正的使用無論是內置的JavaScriptSerializer或Newtonsoft JSON庫。

序列化代碼

var settings = new Newtonsoft.Json.JsonSerializerSettings(); 
settings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects; 

Newtonsoft.Json.JsonConvert.SerializeObject(AnInitializedScoresheet, Newtonsoft.Json.Formatting.None, settings); 

反串行化代碼

return Newtonsoft.Json.JsonConvert.DeserializeObject(returnedStringFromClient, typeof(Scoresheet)); 
//Scoresheet contains a list of observationgroups 

,我得到的是

「無法創建類型ProjectXCommon.DataStores.Observation實例的錯誤。類型是一個接口或抽象類,不能被瞬間化。「

任何幫助將不勝感激!

+0

我敢肯定,它關係到你的'名單'的解串器試圖實例化一個類型的'Observation'不是特定類型它實際上是。使用Newtonsoft,您可以通過添加自己的Converter來覆蓋部分反序列化(這裏是一個示例https://gist.github.com/1140171)我不確定這對您有多大幫助,但我並不完全確定但確實如此。 :) – Buildstarted

+0

json樣本會有所幫助 – Frank

回答

28

您還沒有添加任何關於反序列化的設置。您需要應用設置爲TypeNameHandling設置爲ObjectAll

像這樣:

JsonConvert.DeserializeObject(
    returnedStringFromClient, 
    typeof(Scoresheet), 
    new JsonSerializerSettings 
    { 
     TypeNameHandling = TypeNameHandling.Objects 
    }); 

文檔:TypeNameHandling setting

+0

Doh!對於那些仍在使用.NET JavascriptSerializer的人,你也可以使用新的JavaScriptSerializer(新的System.Web.Script.Serialization.SimpleTypeResolver())。Deserialize(returnedStringFromClient,typeof(Scoresheet));' – Chainlink

+1

從RavenDB build 499開始(RavenDB使用JSON。NET)在使用通用列表(其中T是接口)時,需要添加[JsonProperty(TypeNameHandling = TypeNameHandling.All)]屬性。這修復了異常「無法創建類型的實例」您的接口「類型是一個接口或抽象類,不能即時。」 – DalSoft