[英]Deserialize to IEnumerable class using Newtonsoft Json.Net
[英]Deserialize an object with an IEnumerable using JSON.NET
考慮以下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; }
}
我正在嘗試使用自定義json轉換器反序列化IEnumerable,它可以是Toaster
或Kettle
。 這里的想法是,一旦我了解了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:'從JsonReader讀取JObject時出錯。 當前JsonReader項不是對象:StartArray。 路徑“電器”
我想這已經到IEnumerable了,而且只是失敗了,我在這里做錯了什么?
注釋此行代碼
public class HouseModel
{
public String Reference { get; set; }
//[JsonConverter(typeof(ApplianceModelConverter))] //=> You don't need this
public IEnumerable<IApplianceModel> Appliances { get; set; }
}
還將Create方法更改為此
protected override IApplianceModel Create(Type objectType, JObject jObject)
{
if (jObject["ApplianceType"] == null) //case sensitive
{
throw new ArgumentException("Missing ApplianceType");
}
//ApplianceType applianceType = jObject.Value<ApplianceType>(); //this might throw invalid cast exception
ApplianceType applianceType = jObject["ApplianceType"].ToObject<ApplianceType>();
switch (applianceType)
{
case ApplianceType.Kettle:
return new KettleModel();
case ApplianceType.Toaster:
return new ToasterModel();
default:
throw new InvalidEnumArgumentException("ApplianceType not supported");
}
}
如果我們正在使用此方法反序列化
string json = "{\"Reference\": \"Bay House 22\",\"Appliances\": [{\"Reference\": \"Kitchen Appliance 1\",\"ApplianceType\": \"0\",\"NumberOfSlots\": 4},{\"Reference\": \"Kitchen Appliance 2\",\"ApplianceType\": \"1\",\"Capacity\": 1500}]}";
HouseModel houseModels = JsonConvert.DeserializeObject<HouseModel>(json, new ApplianceModelConverter());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.