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

时间:2015-10-15 23:04:47

标签: c# json.net

我有一个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作为建议而不是要求吗?我可以编写一种可以处理这种情况的自定义转换器吗?

1 个答案:

答案 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是可能的。