1

I have implemented a custom JsonConverter to deserialize concrete classes when all we know about is the interface that is using them. given this, I have overridden the ReadJson method with the following:

public class MyConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(IMyInterface));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);

        if (jsonObject["Type"].Value<string>() == "MyType")
            return jsonObject.ToObject<MyConcrete>(serializer);
    }
}

On the interface I have added the following decoration:

[JsonConverter(typeof(MyConverter))]
public interface IMyInterface { ... }

The issue I seem to be having is that when deserialization is attempted, I keep getting StackOverflow exception, and I think that it is going around this custom converter for each element in the JSON structure.. which there are quite a few(!)

If I remove the decoration of the interface and instead add the custom converter to the call the converter manually... it works fine!

var jsonSerializerSettings = new JsonSerializerSettings
{
    Converters = { new MyConverter() }
};

Is there a way I can resolve this without calling the customer converter specifically? I am concerned about unexpected behavior on deserialization of objects that don't need the custom JsonConverter. Thoughts?

m1nkeh
  • 1,337
  • 23
  • 45
  • I think you can use either of the options from [this answer](https://stackoverflow.com/a/45554062/3744182) to [How to call JsonConvert.DeserializeObject and disable a JsonConverter applied to a base type via `[JsonConverter]`?](https://stackoverflow.com/q/45547123/3744182). I'm a little surprised that this is necessary when the converter is applied to an interface rather than to the base class, however. – dbc Feb 20 '18 at 12:52
  • "I think that it is going around this custom converter for each element in the JSON structure" - why do you only think this? Open up a debugger and actually check. – Chris Feb 20 '18 at 12:57
  • i did check.. it is.. i was more after validation, and understanding of "why" ;) – m1nkeh Feb 20 '18 at 12:58
  • OK, I checked. Firstly, `CanConvert` isn't called when a converter is applied directly via attributes. Secondly, when getting the `JsonConverterAttribute` for a concrete type, [`JsonTypeReflector.GetAttribute`](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs#L303) is called, which checks all the interfaces implemented by the type and returns the first converter found. That's the cause of the infinite recursion. To fix, use one of the answers from https://stackoverflow.com/q/45547123/3744182 – dbc Feb 20 '18 at 13:10
  • awesome, thanks for the validation of my thinking... shame i couldn't confirm that myself.. how did you work out the CanConvert isn't used (just debugging?), and also how did you "prove" the second point.. always good to understand how to fish for yourself – m1nkeh Feb 20 '18 at 13:13
  • *how did you work out the CanConvert isn't used* - I don't remember, I've known that for quite a while. It's mentioned [here](https://stackoverflow.com/a/26018381) for example. *how did you "prove" the second point* - I set a break in [`DefaultContractResolver.CreateObjectContract()`](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs#L314) and debugged it. Should I make this a duplicate of https://stackoverflow.com/q/45547123/3744182? – dbc Feb 20 '18 at 13:19
  • not yet, i will read that other question tomorrow and check it through, ta for your help. – m1nkeh Feb 20 '18 at 13:21
  • worked like a charm, i needed to add a Json constructor to my concrete class as they require thing passed to them on creation, but other than that ace - thanks... i shall follow up on the other post – m1nkeh Feb 20 '18 at 13:54

0 Answers0