NJsonSchema icon indicating copy to clipboard operation
NJsonSchema copied to clipboard

Unknown subtype causes Stackoverflow exception at deserialization

Open ryanheath opened this issue 5 months ago • 0 comments

See example code & payload

[JsonInheritanceConverter(typeof(Event), "$type")]
[JsonInheritanceAttribute("Arrival", typeof(Arrival))]
[JsonInheritanceAttribute("Departure", typeof(Departure))]
public partial class Event
{
}

public partial class Data
{
    [JsonPropertyName("events")]
    public ICollection<Event> Events { get; set; } = new System.Collections.ObjectModel.Collection<Event>();
}

{ "events": [{"$type":"Cancel"}] }

trying to deserialize the payload with a (yet) unknown subtype "Cancel" causes a stackoverflow exception.

I think the problem is with the generated JsonInheritanceConverter<TBase>.GetObjectSubtype. It always returns a value but it should return null when it cannot find any known subtype.

private System.Type GetObjectSubtype(System.Type objectType, string discriminator)
{
    foreach (var attribute in System.Reflection.CustomAttributeExtensions.GetCustomAttributes<JsonInheritanceAttribute>(System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType), true))
    {
        if (attribute.Key == discriminator)
            return attribute.Type;
    }

    return objectType;  // <--- this should return null!
}

The only place where GetObjectSubtype is called is in JsonInheritanceConverter<TBase>.GetDiscriminatorType which tests for null(!) ...

When the fix (returning null when subtype is not found) is applied the code throws the correct exception

throw new System.InvalidOperationException("Could not find subtype of '" + objectType.Name + "' with discriminator '" + discriminatorValue + "'.");

ryanheath avatar Sep 07 '24 12:09 ryanheath