Force Json.NET to ignore $ type if it is incompatible

I had a type property IReadOnlyList<RoadLaneDto>. To be compatible elsewhere, I changed it to RoadLaneDto[]. Now when I deserialize my old data, I get this error:

Newtonsoft.Json.JsonSerializationException: Type specified in 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 'is incompatible with' Asi.Shared.Interfaces.DTOs.Map.RoadLaneDto [], Asi.Shared.Interfaces, Version = 1.0. 0.0, Culture = Neutral, PublicKeyToken = null '. Path 'Shape [0] .Lanes. $ Type ', line 78, position 132.

What is the right approach for their compatibility? Can I make an offer $type, not a demand? Can I write my own converter to handle this situation?

+2
source share
1 answer

, : ( ) . , , , Json.NET, HashSet<T> ICollection<T>, 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 , a > 1.

+1

Source: https://habr.com/ru/post/1691906/


All Articles