【问题标题】:JsonConvert deserialize an array of abstract classesJsonConvert 反序列化抽象类数组
【发布时间】:2018-02-21 16:14:40
【问题描述】:

假设我有以下类结构(Building 是一个抽象类):

public class Street
{
    public string StreetName { get; set; }

    public Building[] Buildings { get; set; }
}

public abstract class Building
{
    public string Name { get; set; }
}

public class House : Building
{
    public int Floors { get; set; }
}

public class Flat : Building
{
    public int WhichFloor { get; set; }
}

然后我在建筑物数组中创建一个带有一些公寓的街道对象:

Flat f1 = new Flat { Name = "Flat 1", WhichFloor = 1 };
Flat f2 = new Flat { Name = "Flat 2", WhichFloor = 2 };

Street street = new Street
{
    StreetName = "Street Name",
    Buildings = new[] { f1, f2 }
};

使用 JsonConvert 然后序列化对象:

var toJson = JsonConvert.SerializeObject(street);

现在我想将 json 转换回街道对象:

var fromJson = JsonConvert.DeserializeObject<Street>(toJson);

这会失败并出现以下错误:

“无法创建 Building 类型的实例。类型是接口或抽象类,无法实例化。路径 'Buildings[0].WhichFloor'”

我如何告诉 JsonConvert 类 Buildings 应该是一组公寓?

【问题讨论】:

标签: c# json.net abstract-class json-deserialization


【解决方案1】:

根据@Evk 的共享链接,您应该在序列化和反序列化时尝试将TypeNameHandling 设置为TypeNameHandling.Auto

var toJson = JsonConvert.SerializeObject(street, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});


var fromJson = JsonConvert.DeserializeObject<Street>(toJson, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});

【讨论】:

  • 我发现最好的结果来自TypeNameHandling.All
【解决方案2】:
public abstract class JsonCreationConverter<T> : JsonConverter
{
    protected abstract T Create(Type objectType, JObject jObject);

    public override bool CanConvert(Type objectType)
    {
        return typeof(T) == objectType;
    }

    public override object ReadJson(JsonReader reader,Type objectType,
        object existingValue, JsonSerializer serializer)
    {
        try
        {
            var jObject = JObject.Load(reader);
            var target = Create(objectType, jObject);
            serializer.Populate(jObject.CreateReader(), target);
            return target;
        }
        catch (JsonReaderException)
        {
            return null;
        }
    }

    public override void WriteJson(JsonWriter writer, object value,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

现在实现这个接口

public class SportActivityConverter : JsonCreationConverter<BaseSportActivity>
{
    protected override BaseSportActivity Create(Type objectType, JObject jObject)
    {
        BaseSportActivity result = null;
        try
        {
            switch ((ESportActivityType)jObject["activityType"].Value<int>())
            {
                case ESportActivityType.Football:
                    result = jObject.ToObject<FootballActivity>();
                    break;

                case ESportActivityType.Basketball:
                    result = jObject.ToObject<BasketballActivity>();
                    break;
            }
            
        }
        catch(Exception ex)
        {
            Debug.WriteLine(ex);
        }

        return result;
        
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 2017-11-06
    • 2012-11-18
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    相关资源
    最近更新 更多