Skip to content

Instantly share code, notes, and snippets.

@chrisoldwood
Last active February 17, 2023 23:16
Show Gist options
  • Save chrisoldwood/b604d69543a5fe5896a94409058c7a95 to your computer and use it in GitHub Desktop.
Save chrisoldwood/b604d69543a5fe5896a94409058c7a95 to your computer and use it in GitHub Desktop.
Example showing infinite loop deserialising polymorphic types with a custom JsonConverter.
namespace JsonTests
{
public class CustomJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(BaseType).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
#if USE_TO_OBJECT
var @object = item.ToObject<DerivedType>();
return @object;
#else // USE_POPULATE
var @object = new DerivedType();
serializer.Populate(item.CreateReader(), @object);
return @object;
#endif
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}
namespace JsonTests
{
[JsonConverter(typeof(CustomJsonConverter))]
public abstract class BaseType
{
public string Value { get; set; }
}
public class DerivedType : BaseType
{
public string DerivedValue { get; set; }
}
public class Container
{
public List<BaseType> Objects { get; set; }
}
}
namespace JsonTests
{
[TestFixture]
public class Tests
{
[Test]
public void Test()
{
const string json =
"{ 'Objects': [" +
" { 'Value': 'test value' } " +
"] }";
#if USE_TO_OBJECT
Assert.That(() => JsonConvert.DeserializeObject<Container>(json),
Throws.InstanceOf<StackOverflowException>());
#else // USE_POPULATE
Assert.That(() => JsonConvert.DeserializeObject<Container>(json),
Throws.Nothing);
#endif
}
}
}
@Melechous
Copy link

Thanks Chris, this was very helpful. I had an example where I was using the toObject method in JsonSerializerSettings and it worked so I was surprised when my new code used that method and was causing the stack overflow exception.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment