Рассмотрим следующие json и модели:
{
"Reference": "Bay House 22",
"Appliances": [
{
"Reference": "Kitchen Appliance 1",
"ApplianceType": "0",
"NumberOfSlots": 4
},
{
"Reference": "Kitchen Appliance 2",
"ApplianceType": "1",
"Capacity": 1500
}
]
}
public class HouseModel
{
public String Reference { get; set; }
[JsonConverter(typeof(ApplianceModelConverter))]
public IEnumerable<IApplianceModel> Appliances { get; set; }
}
public interface IApplianceModel
{
String Reference { get; set; }
ApplianceType ApplianceType { get; set; } // this is an enum
}
public class ToasterModel : IApplianceModel
{
public String Reference { get; set; }
public ApplianceType ApplianceType { get; set; }
public Int32 NumberOfSlots { get; set; }
}
public class KettleModel : IApplianceModel
{
public String Reference { get; set; }
public ApplianceType ApplianceType { get; set; }
public Int32 Capacity { get; set; }
}
Я пытаюсь десериализовать IEnumerable, который может быть Toaster
или Kettle
, используя специальный конвертер json. Идея в том, что я могу вернуть конкретный тип, как только узнаю, что такое ApplianceType, посмотрев на json. Я следил за этой публикацией stackoverflow, чтобы попытаться заставить это работать, но безуспешно.
Вот код конвертера:
public abstract class JsonCreationConverter<T> : JsonConverter
{
protected abstract T Create(Type objectType, JObject jObject);
public override Boolean CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override Boolean CanWrite
{
get { return false; }
}
public override Object ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
{
// Load JObject from stream
JObject jObject = JObject.Load(reader);
// Create target object based on JObject
T target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
public class ApplianceModelConverter: JsonCreationConverter<IApplianceModel>
{
protected override IApplianceModel Create(Type objectType, JObject jObject)
{
if (jObject["applianceType "] == null)
{
throw new ArgumentException("Missing ApplianceType");
}
ApplianceType applianceType = jObject.Value<ApplianceType>();
switch (applianceType )
{
case ApplianceType.Kettle:
return new KettleModel();
case ApplianceType.Toaster:
return new ToasterModel();
default:
throw new InvalidEnumArgumentException("ApplianceType not supported");
}
}
}
В настоящее время я получаю исключение при выполнении этой строки: JObject jObject = JObject.Load(reader);
в JsonCreationConverter
Newtonsoft.Json.JsonReaderException: 'Ошибка чтения JObject из
JsonReader. Текущий элемент JsonReader не является объектом: StartArray. Дорожка
'Техника'
Полагаю, что он достигает IEnumerable и просто не работает, что я тут не так делаю?