2011-08-17 2 views
25

다형성 객체 배열과 관련된 JSON 직렬화에 문제가 있습니다. 나는 serialization을위한 솔루션을 시도했다. herehere은 직렬화에 매우 효과적이지만, 모두 deserialization에서 폭발적이다. 다음과 같이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를 사용하면 자신의 변환기를 추가하여 역 직렬화의 일부를 무시할 수 있습니다 (여기에 예제가 있습니다 https://gist.github.com/1140171). 나는 이것이 전적으로 확실하지는 않지만 이것이 얼마나 도움이되는지 확신하지 못합니다. 그러나 이것은 꽤 확실합니다. :) – Buildstarted

+0

json 샘플이 도움이 될 것입니다 – Frank

답변

28

비 직렬화시 설정을 추가하지 않았습니다. TypeNameHandlingObject 또는 All으로 설정된 설정을 적용해야합니다.

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

: 나는 그것이 당신의 '목록 에 관련이 있음을 확신 TypeNameHandling setting

+0

Doh! 여전히 .NET JavascriptSerializer를 사용하는 사용자는 새 JavaScriptSerializer (새 System.Web.Script.Serialization.SimpleTypeResolver())를 사용할 수 있습니다 .Derialialize (returnedStringFromClient, typeof (Scoresheet)); ' – Chainlink

+1

RavenDB 빌드 499 (RavenDB JSON을 사용합니다.NET)에서 T가 인터페이스 인 generic List를 사용할 때는 [JsonProperty (TypeNameHandling = TypeNameHandling.All)] 특성을 추가해야합니다. 이것은 "유형의 인스턴스를 생성 할 수 없습니다 '인터페이스'유형이 인터페이스 또는 추상 클래스이고 인스턴스를 생성 할 수 없습니다."라는 예외를 수정합니다. – DalSoft