我遇到了涉及多态对象数组的JSON反序列化问题。我已经尝试了序列化的解决方案here和here,它们非常适合序列化,但是在反序列化方面都很好。
我的班级结构如下:
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类型的实例.Type是接口或抽象类,无法立即显示。”
非常感谢任何帮助!
答案 0 :(得分:28)
反序列化时未添加任何设置。您需要将TypeNameHandling
设置为Object
或All
来应用设置。
像这样:
JsonConvert.DeserializeObject(
returnedStringFromClient,
typeof(Scoresheet),
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
答案 1 :(得分:2)
使用此JsonKnownTypes,类似的方法:
[JsonConverter(typeof(JsonKnownTypeConverter<BaseClass>))]
[JsonKnownType(typeof(Base), "base")]
[JsonKnownType(typeof(Derived), "derived")]
public class Base
{
public string Name;
}
public class Derived : Base
{
public string Something;
}
现在,当您在json中序列化对象时,将添加"$type"
和"base"
和"derived"
值,并将其用于反序列化
序列化列表示例:
[
{"Name":"some name", "$type":"base"},
{"Name":"some name", "Something":"something", "$type":"derived"}
]