簡體   English   中英

使用JSON.NET使用IEnumerable反序列化對象

[英]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,它可以是ToasterKettle 這里的想法是,一旦我了解了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM