Skip to content

Conversation

@layomia
Copy link
Contributor

@layomia layomia commented Aug 14, 2020

Fixes #36621.

The issue repro'd when a converter had this sort of CanConvert implementation:

public override bool CanConvert(Type typeToConvert) =>
    typeToConvert == typeof(TestStruct) || typeToConvert == typeof(TestStruct?);

This caused the converter itself to be set as the converter for a nullable-struct property, rather than a NullableConverter wrapping the custom converter. This means we were trying to set an arg of T rather than T? in the generated IL method which called the setter, which subsequently caused the InvalidProgramException.

The serializer automatically uses an available JsonConverter<T> when no JsonConverter<T?> is present i.e. the sample CanConvert implementation above is redundant. Without this override, the issue did not repro as a NullableConverter instance wrapping the custom converter is used.

Rather than leaking an InvalidProgramException, we change the exception to an InvalidOperationException with a meaningful message. The resolution is for JsonConverter<T> converters not to have the above kind of CanConvert implementation, where the typeToConvert == typeof(TestStruct?) is what would cause an exception.

@layomia layomia added this to the 5.0.0 milestone Aug 14, 2020
@layomia layomia self-assigned this Aug 14, 2020
@layomia layomia changed the title Wrap non-nullable struct converters in NullableOfT converter when they explicitly handle nullable structs Throw when non-nullable struct converters indicate that they handle nullable structs Aug 14, 2020
</data>
</root>
<data name="ConverterCanConvertNullableRedundant" xml:space="preserve">
<value>The converter '{0}' which handles type '{1}' should not indicate that it also handles type '{2}'. The converter will be used automatically if no converter which handles type '{2}' is provided.</value>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest some rewording like
The converter '{0}' handles type '{1}' but is being asked to convert type '{2}'. Either create a separate converter for type '{2}' or change the converter's CanConvert to only return 'true' for a single type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also point to the custom converter docs here and elsewhere when we have relevant samples up. cc @tdykstra

Copy link
Contributor

@steveharter steveharter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some misc rewording comments, but otherwise LGTM.

@layomia layomia merged commit 99829d5 into dotnet:master Aug 15, 2020
@layomia layomia deleted the invalidprogramexception branch August 15, 2020 02:24
@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[System.Text.Json] System.InvalidProgramException when deserializing json.

2 participants