JsonConvert 反序列化抽象数组 类
JsonConvert deserialize an array of abstract classes
假设我有以下 class 结构(建筑是抽象的 class):
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);
失败并出现以下错误:
"Could not create an instance of type Building. Type is an interface or abstract class and cannot be instantiated. Path 'Buildings[0].WhichFloor'"
我如何告诉 JsonConvert class 建筑物应该是一组公寓?
根据@Evk 的分享 link,您应该尝试在序列化和反序列化时将 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
});
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;
}
}
假设我有以下 class 结构(建筑是抽象的 class):
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);
失败并出现以下错误:
"Could not create an instance of type Building. Type is an interface or abstract class and cannot be instantiated. Path 'Buildings[0].WhichFloor'"
我如何告诉 JsonConvert class 建筑物应该是一组公寓?
根据@Evk 的分享 link,您应该尝试在序列化和反序列化时将 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
});
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;
}
}