如果Json.NET不兼容,请使其忽略$ type

我有一个IReadOnlyList类型的属性。 为了兼容其他地方,我将其更改为RoadLaneDto[] 。 现在,当我反序列化旧数据时,我收到此错误:

Newtonsoft.Json.JsonSerializationException:在JSON中指定的类型’System.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’与’Asi.Shared.Interfaces.DTOs.Map.RoadLaneDto [],Asi.Shared.Interfaces,Version = 1.0不兼容.0.0,Culture = neutral,PublicKeyToken = null’。 Path’Shapes [0] .Lanes。$ type’,第78行,第132位。

使这些兼容的正确方法是什么? 我可以将$type作为建议而不是要求吗? 我可以编写一种可以处理这种情况的自定义转换器吗?

一般情况下,我不建议序列化集合类型,正是出于这个原因:您希望在没有序列化问题的情况下自由更改集合类型(尽管不一定是集合的类型)。 如果要实现具有与Json.NET的默认值不同的特定集合类型的collection-interface-valued属性,例如ICollectionHashSet ICollection ,则可以在包含类的默认构造函数中分配它,Json.NET将使用预先分配的集合。 要仅序列化对象类型而不是序列类型,请设置TypeNameHandling = TypeNameHandling.Objects

话虽这么说,以下转换器将在反序列化排名1的数组时吞下类型信息:

 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(); } } 

然后你就可以使用它:

 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 }; 

Json.NET确实支持多维数组,因此可以扩展对rank> 1数组的支持。