我有一个IReadOnlyList<RoadLaneDto>
类型的属性。为了与其他地方兼容,我将其更改为RoadLaneDto[]
。现在,当我反序列化旧数据时,我收到此错误:
Newtonsoft.Json.JsonSerializationException:在JSON&System; Series.Collections.Generic.List`1 [[Asi.Shared.Interfaces.DTOs.Map.RoadLaneDto,Asi.Shared.Interfaces,Version = 1.0]中指定的类型。 0.0,Culture = neutral,PublicKeyToken = null]],mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089&#39;与&#39; Asi.Shared.Interfaces.DTOs.Map.RoadLaneDto [],Asi.Shared.Interfaces,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null&#39;不兼容。路径&#39;形状[0] .Lanes。$ type&#39;,第78行,第132位。
使这些兼容的正确方法是什么?我可以将$type
作为建议而不是要求吗?我可以编写一种可以处理这种情况的自定义转换器吗?
答案 0 :(得分:2)
一般情况下,我不建议序列化集合类型,正是出于这个原因:您希望可以自由更改集合类型(尽管不一定是集合类型 item )序列化问题。如果要实现一个collection-interface-valued属性,其特定的集合类型与Json.NET的默认值不同,比如ICollection<T>
为public class IgnoreArrayTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsArray && objectType.GetArrayRank() == 1 && objectType.HasElementType;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (!CanConvert(objectType))
throw new JsonSerializationException(string.Format("Invalid type \"{0}\"", objectType));
if (reader.TokenType == JsonToken.Null)
return null;
var token = JToken.Load(reader);
var itemType = objectType.GetElementType();
return ToArray(token, itemType, serializer);
}
private static object ToArray(JToken token, Type itemType, JsonSerializer serializer)
{
if (token == null || token.Type == JTokenType.Null)
return null;
else if (token.Type == JTokenType.Array)
{
var listType = typeof(List<>).MakeGenericType(itemType);
var list = (ICollection)token.ToObject(listType, serializer);
var array = Array.CreateInstance(itemType, list.Count);
list.CopyTo(array, 0);
return array;
}
else if (token.Type == JTokenType.Object)
{
var values = token["$values"];
if (values == null)
return null;
return ToArray(values, itemType, serializer);
}
else
{
throw new JsonSerializationException("Unknown token type: " + token.ToString());
}
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
,则可以在包含类的默认构造函数,Json.NET将使用预先分配的集合。要仅序列化对象类型而不是序列类型,请设置TypeNameHandling = TypeNameHandling.Objects
。
话虽这么说,以下转换器在反序列化排名1的数组时会吞下类型信息:
public class RootObject
{
[JsonProperty(TypeNameHandling = TypeNameHandling.None)] // Do not emit array type information
[JsonConverter(typeof(IgnoreArrayTypeConverter))] // Swallow legacy type information
public string[] Lanes { get; set; }
}
然后你就可以使用它:
var settings = new JsonSerializerSettings { Converters = new JsonConverter[] { new IgnoreArrayTypeConverter() }, TypeNameHandling = TypeNameHandling.All };
或者,您可以在设置中全局使用转换器,并让它吞下所有阵列的类型信息:
FirstConverter
Json.NET确实支持多维数组,因此扩展了对rank&gt;数组的支持。 1是可能的。