Подтвердить что ты не робот

JSON 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. Тип - это интерфейс или абстрактный класс и не может быть создан."

Любая помощь будет очень признательна!

4b9b3361

Ответ 1

Вы не добавили никаких настроек при десериализации. Вам необходимо применить настройки с TypeNameHandling, установленными на Object или All.

Вот так:

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

Документация: Настройка TypeNameHandling