Наследование и сериализация

Рейтинг: 3Ответов: 2Опубликовано: 03.04.2015

Имеется базовый класс AudioObject, от которого наследуются два класса: Audio и AudioUser. Также имеем класс AudioList, в котором есть поле List<AudioObject>. В этом поле может храниться список объектов смешанных типов: Audio и AudioUser.

public class AudioObject
{
}

public class Audio : AudioObject
{
    public uint id { get; set; }
    public string title { get; set; }
}

public class AudioUser : AudioObject
{
    public string id { get; set; }
    public string name { get; set; }
}

public class AudioList
{
    public int count { get; set; }
    public List<AudioObject> list { get; set; }
}

Попытаемся сериализовать и десириализовать объкт AudioList:

AudioList list = new AudioList();
list.count = 1;
list.list = new List<AudioObject> { new Audio { id = 1, title = "Test"} };

string serialized = JsonConvert.SerializeObject(list);

AudioList newList = JsonConvert.DeserializeObject<AudioList>(serialized);
Audio audio = newList.list[0] as Audio;

Сериализация происходит успешно, но вот десериализация возвращает нулевые объекты из списка List<AudioObject>.

В чем моя ошибка?

Ответы

▲ 2Принят

You are getting null for audio because items in deserialized list are instances of base AudioObject class - according to List<> declaration. Add type information to [de]serialization:

AudioList list = new AudioList();
list.count = 1;
list.list = new List<AudioObject> { new Audio { id = 1, title = "Test"} };

JsonSerializerSettings settings = new JsonSerializerSettings() {
  TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All 
};
string serialized = JsonConvert.SerializeObject(list, settings);

AudioList newList = JsonConvert.DeserializeObject<AudioList>(serialized, settings);
Audio audio = newList.list[0] as Audio;
▲ 3

Используйте настройку TypeNameHandling, чтобы информация о типах сохранялась в JSON:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
    // или All для того, чтобы десериализовать не только объекты дочерних типов,
    // но и коллекции разных типов (IList/IEnumerable)
};
string serialized = JsonConvert.SerializeObject(list, settings);

AudioList newList = JsonConvert.DeserializeObject<AudioList>(serialized, settings);
Audio audio = newList.list[0] as Audio; // != null