Как десериализовать JSON в IEnumerable <BaseType> с помощью Newtonsoft JSON.NET
учитывая этот JSON:
[
{
"$id": "1",
"$type": "MyAssembly.ClassA, MyAssembly",
"Email": "[email protected]",
},
{
"$id": "2",
"$type": "MyAssembly.ClassB, MyAssembly",
"Email": "[email protected]",
}
]
и эти классы:
public abstract class BaseClass
{
public string Email;
}
public class ClassA : BaseClass
{
}
public class ClassB : BaseClass
{
}
Как я могу десериализовать JSON в:
IEnumerable<BaseClass> deserialized;
Я не могу использовать JsonConvert.Deserialize<IEnumerable<BaseClass>>()
, потому что он жалуется, что BaseClass
является абстрактным.
Ответы
Ответ 1
вам нужно:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
string strJson = JsonConvert.SerializeObject(instance, settings);
поэтому JSON выглядит так:
{
"$type": "System.Collections.Generic.List`1[[MyAssembly.BaseClass, MyAssembly]], mscorlib",
"$values": [
{
"$id": "1",
"$type": "MyAssembly.ClassA, MyAssembly",
"Email": "[email protected]",
},
{
"$id": "2",
"$type": "MyAssembly.ClassB, MyAssembly",
"Email": "[email protected]",
}
]
}
то вы можете десериализировать его:
BaseClass obj = JsonConvert.DeserializeObject<BaseClass>(strJson, settings)
Документация: Настройка TypeNameHandling
Ответ 2
используйте следующую конструкцию JsonSerializerSettings при десериализации:
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects
})
Ответ 3
Вот способ сделать это без заполнения типа $в json.
Конвертер Json:
public class FooConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(BaseFoo));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
if (jo["FooBarBuzz"].Value<string>() == "A")
return jo.ToObject<AFoo>(serializer);
if (jo["FooBarBuzz"].Value<string>() == "B")
return jo.ToObject<BFoo>(serializer);
return null;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
используя его:
var test = JsonConvert.DeserializeObject<List<BaseFoo>>(result, new JsonSerializerSettings()
{
Converters = { new FooConverter() }
});
взято из здесь
Ответ 4
Вы также можете обернуть перечислимое в класс:
class Wrapper
{
IEnumerable<BaseClass> classes;
}
затем сериализуем и десериализуем это.