Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I (de)serialize a list of type that requires a custom JsonConverter?

I have a class that needs serializing/deserializing. It looks like this:

public class Animation
{
    [JsonProperty]
    private readonly string name;

    [JsonProperty]
    private readonly IList<Rectangle> frames;
}

However, Json.Net doesn't play nice with XNA's Rectangle class. It needs a custom JsonConverter, which I managed to scrape together. This works fine on classes with a single Rectangle property, like:

public class Sprite
{
    [JsonConverter(typeof(RectangleConverter))]
    [JsonProperty]
    private readonly Rectangle frame;
}

But how do I apply that converter to the list of Rectangles in my Animation class?

like image 317
Big McLargeHuge Avatar asked Nov 18 '25 08:11

Big McLargeHuge


1 Answers

According to the doc, the XNA Rectangle struct is marked as having a TypeConverter, and by default type converters always return true when asked to convert to string. Because of this Json.Net will by default try to create a string contract instead of an object contract, which will lead to an error when used with your RectangleConverter. This can be fixed by using a custom ContractResolver to tell Json.Net that Rectangle should be treated as an object, not a string. We can also set the converter inside the resolver, so you do not need to decorate your class properties with a [JsonConverter] attribute wherever you use a Rectangle.

Here is the code you would need:

class CustomResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        if (objectType == typeof(Rectangle) || objectType == typeof(Rectangle?))
        {
            JsonContract contract = base.CreateObjectContract(objectType);
            contract.Converter = new RectangleConverter();
            return contract;
        }
        return base.CreateContract(objectType);
    }
}

To use the resolver, add it to the serializer settings and pass that to DeserializeObject() or SerializeObject() like this:

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CustomResolver();

Animation anim = JsonConvert.DeserializeObject<Animation>(json, settings);
like image 100
Brian Rogers Avatar answered Nov 20 '25 21:11

Brian Rogers