tag:blogger.com,1999:blog-6628985022531866193.post1545050006711387452..comments2024-02-12T17:37:05.629+00:00Comments on The OldWood Thing: Stack Overflow With Custom JsonConverterChris Oldwoodhttp://www.blogger.com/profile/18183909440298909448noreply@blogger.comBlogger6125tag:blogger.com,1999:blog-6628985022531866193.post-1912123043413307692020-11-26T07:46:28.662+00:002020-11-26T07:46:28.662+00:00I am strugging with the same problem, and Peter Ru...I am strugging with the same problem, and Peter Rudeman is definitely correct. The problem is that is applied the custom converter when trying to deserialize the implementing (sub)type as well, because it is inherited.<br /><br />We had used the "new T()" solution and serializer.Populate, but then suddenly someone introduced a [JsonConstructor] property, and we didn't understand at all why the attribute "wasn't working". Except it was. But we just called the empty one too, in our converter. This is not an easy one. Trying to find a good solution without re-implementing much of the logic here:<br /><br />https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs#L1934erikbrahttps://www.blogger.com/profile/00713297116618581641noreply@blogger.comtag:blogger.com,1999:blog-6628985022531866193.post-44901948825916558652020-06-11T23:09:22.906+01:002020-06-11T23:09:22.906+01:00Thanks Chris! You saved quite a bit of head scratc...Thanks Chris! You saved quite a bit of head scratching.Matthttps://www.blogger.com/profile/03236762360630571563noreply@blogger.comtag:blogger.com,1999:blog-6628985022531866193.post-67180638886856744772020-05-14T22:56:13.546+01:002020-05-14T22:56:13.546+01:00I think the problem is that the JsonConverter attr...I think the problem is that the JsonConverter attribute is inheritable. When Newtonsoft tries to deserialize the subtype, it sees the same converter attribute. But it doesn't call "CanConvert" to see if the inherited converter applies to the subtype. Pretty clearly a bug in the library IMHO.Peter Rudermanhttps://www.blogger.com/profile/17208643236636833176noreply@blogger.comtag:blogger.com,1999:blog-6628985022531866193.post-70093333652330923002019-10-19T10:30:18.127+01:002019-10-19T10:30:18.127+01:00Brilliant, thank you, best solution to avoid the s...Brilliant, thank you, best solution to avoid the stack overflow I could find :)Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-6628985022531866193.post-14390554950868092142019-09-14T16:10:55.534+01:002019-09-14T16:10:55.534+01:00Essentially the deserialization engine has many co...Essentially the deserialization engine has many converters and the base type should really be an interface.<br /><br />Removing the converter at runtime is basically out of the question, so my generic solution is at least satisfactory for meMatthew Lyonhttps://www.blogger.com/profile/07289850282563735819noreply@blogger.comtag:blogger.com,1999:blog-6628985022531866193.post-25347540293457351472019-09-14T15:22:17.733+01:002019-09-14T15:22:17.733+01:00I'm following the same thinking that you had a...I'm following the same thinking that you had and I think I've come to understand what is happening.<br />Adding a custom JsonConverter is essentially a short circuit within Newtonsoft.Json. The mistake we're making is to consider our CustomJsonConverter as an overload of existing functionality when really it is a hook into the pipeline.<br />I attempted to call base.ReadJson within my customer converter and it created the loop for me.<br />So unless we can remove the converter at runtime from that pipeline or create a new one without it, we'll encounter this loop.<br />This is essentially what the "deserializing polymorphic classes" question did by not applying the custom converter to sub types (and not using it as an attribute so that it isn't automatically applied). The converter is applied to the base class and then decides which child class to run through the pipeline. Those child classes will not have the Jsonconverter attribute and so will not encounter the loop. It works but in my mind is brittle.<br />My solution was to use generics, create an instance of the class and use populate.<br />public class CustomConverter : Jsonconverter where T: new()<br />public override object ReadJson(...)<br />{<br />JObject jObject = JObject.Load(reader);<br />var instance = new T();<br />serializer.Populate(jObject.CreateReader(), instance);<br />return instance;<br />}Matthew Lyonhttps://www.blogger.com/profile/07289850282563735819noreply@blogger.com