Отключить класс IEnumerable с помощью Newtonsoft Json.Net
У меня есть проект, который в настоящее время использует Json.Net для классов десериализации Json, таких как:
public class Foo {
public Guid FooGuid { get; set; }
public string Name { get; set; }
public List<Bar> Bars { get; set; }
}
public class Bar {
public Guid BarGuid { get; set; }
public string Description { get; set; }
}
Пока это работает нормально.
Чтобы упростить итерацию в один момент, я выполнил Foo
class IEnumerable<Bar>
следующим образом:
public class Foo : IEnumerable<Bar> {
public Guid FooGuid { get; set; }
public string Name { get; set; }
public List<Bar> Bars { get; set; }
public IEnumerator<Bar> GetEnumerator()
{
return Bars.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Bar {
public Guid BarGuid { get; set; }
public string Description { get; set; }
}
Но тогда это не позволяет десериализовать объект. Ошибка запуталась, поскольку он сказал, что не может десериализовать поле FooGuid
, но удаление интерфейса IEnumerable
снова работает.
Проблема одинакова в средах MonoTouch и MonoDroid в симуляторе или устройстве.
Любая подсказка о том, как заставить его работать?
Добавлен код для воспроизведения этой проблемы:
public static class Tests {
public static void SerializeAndDeserializeFoo() {
// Serialize and deserialize Foo class
var element = new Foo
{
FooGuid = Guid.NewGuid(),
Name = "Foo name",
Bars = new List<Bar> {
new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" }
}
};
var serializedObject = JsonConvert.SerializeObject(element);
Console.WriteLine("Serialized Foo element: {0}", serializedObject);
// Exception if Foo implements IEnumerable
var deserializedObject = JsonConvert.DeserializeObject<Foo>(serializedObject);
Console.WriteLine("Foo deserialization worked!");
}
public static void SerializeAndDeserializeEnumerableFoo() {
// Serialize and deserialize Foo class
var element = new EnumerableFoo
{
FooGuid = Guid.NewGuid(),
Name = "Foo name",
Bars = new List<Bar> {
new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" },
new Bar { BarGuid = Guid.NewGuid(), Description = "Bar description" }
}
};
var serializedObject = JsonConvert.SerializeObject(element);
Console.WriteLine("Serialized EnumerableFoo element: {0}", serializedObject);
try {
// Exception if Foo implements IEnumerable
var deserializedObject = JsonConvert.DeserializeObject<EnumerableFoo>(serializedObject);
Console.WriteLine("EnumerableFoo deserialization worked!");
}
catch (Exception e){
Console.WriteLine("EnumerableFoo deserialization failed!");
throw;
}
}
}
public class EnumerableFoo : IEnumerable<Bar> {
public Guid FooGuid { get; set; }
public string Name { get; set; }
public List<Bar> Bars { get; set; }
public IEnumerator<Bar> GetEnumerator()
{
return Bars.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Foo {
public Guid FooGuid { get; set; }
public string Name { get; set; }
public List<Bar> Bars { get; set; }
}
public class Bar {
public Guid BarGuid { get; set; }
public string Description { get; set; }
}
Пример проекта: https://www.dropbox.com/s/27i58aiz71dylkw/IEnumerableJson.zip
Ответы
Ответ 1
От Документация Json.Net:
IEnumerable, списки и массивы
Списки .NET(типы, наследующие от IEnumerable) и массивы .NET преобразуются в массивы JSON. Поскольку массивы JSON поддерживают только диапазон значений, а не свойства, любые дополнительные свойства и поля, объявленные в коллекциях .NET, не сериализуются. В ситуациях, когда массив JSON не нужен, JsonObjectAttribute может быть помещен в тип .NET, который реализует IEnumerable, чтобы заставить тип быть сериализованным как объект JSON.
Другими словами, поскольку ваш класс реализует IEnumerable<T>
, Json.Net считает, что это список. Чтобы обойти это, просто украсьте свой класс атрибутом [JsonObject]
. Это заставит Json.Net сериализовать и десериализовать его как обычный класс, который вам нужен в этом случае.
[JsonObject]
public class EnumerableFoo : IEnumerable<Bar>
{
...
}