-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
JsonSerializer.Deserialize() throws a NullReferenceException when the following conditions are met:
- The type being deserialized has a
requiredproperty - The JSON contains a property name not present in the type being deserialized
- The
JsonTypeInfoargument is source-generated
Reproduction Steps
- Install the latest build of the .NET SDK (
10.0.100-preview.7.25318.104at the time of writing) - Create a new console app (
dotnet new console) - Replace
Program.cswith the following content:
using System.Text.Json;
using System.Text.Json.Serialization;
// Note the additional "Baz" property
var json = """
{
"Bar": "asdf",
"Baz": "hello"
}
""";
_ = JsonSerializer.Deserialize(json, MyJsonSerializerContext.Default.Foo);
class Foo
{
// Note the use of 'required' here
public required string? Bar { get; set; }
}
[JsonSerializable(typeof(Foo))]
partial class MyJsonSerializerContext : JsonSerializerContext;- Observe that a
NullReferenceExceptiongets thrown in the call toJsonSerializer.Deserialize().
Expected behavior
No exception gets thrown.
Actual behavior
A NullReferenceException gets thrown.
Regression?
This seems to have regressed in version 10.0.0-preview.6.25314.101 of Microsoft.NETCore.App.
I was unable to reproduce the issue in version 10.0.0-preview.6.25302.104.
Known Workarounds
None of these are ideal, but:
- Use
[JsonRequired]for required properties instead of making themrequired - Don't use the JSON source generator
- Sanitize the JSON to not include extra properties
Configuration
.NET SDK: 10.0.100-preview.7.25318.104
OS: Windows 11 Enterprise Build 26100.4349
Architecture: x64
I don't believe the issue is specific to this configuration, but I haven't verified this.
Other information
The line throwing the exception is:
runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs
Line 135 in 3c5f74a
| if (!propertyInfo.Options.AllowDuplicateProperties) |
(propertyInfo.Options is null)
The full stack trace is:
System.Text.Json.dll!System.Text.Json.ReadStackFrame.MarkPropertyAsRead(System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo) Line 135
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs(135)
System.Text.Json.dll!System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter<Foo>.TryLookupConstructorParameter(System.ReadOnlySpan<byte> unescapedPropertyName, ref System.Text.Json.ReadStack state, System.Text.Json.JsonSerializerOptions options, out System.Text.Json.Serialization.Metadata.JsonPropertyInfo jsonPropertyInfo, out System.Text.Json.Serialization.Metadata.JsonParameterInfo jsonParameterInfo) Line 634
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs(634)
System.Text.Json.dll!System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter<Foo>.OnTryRead(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options, ref System.Text.Json.ReadStack state, out Foo value) Line 59
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs(59)
System.Text.Json.dll!System.Text.Json.Serialization.JsonConverter<System.__Canon>.TryRead(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options, ref System.Text.Json.ReadStack state, out System.__Canon value, out bool isPopulatedValue) Line 253
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs(253)
System.Text.Json.dll!System.Text.Json.Serialization.JsonConverter<Foo>.ReadCore(ref System.Text.Json.Utf8JsonReader reader, out Foo value, System.Text.Json.JsonSerializerOptions options, ref System.Text.Json.ReadStack state) Line 40
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs(40)
System.Text.Json.dll!System.Text.Json.Serialization.Metadata.JsonTypeInfo<System.__Canon>.Deserialize(ref System.Text.Json.Utf8JsonReader reader, ref System.Text.Json.ReadStack state) Line 22
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.ReadHelper.cs(22)
System.Text.Json.dll!System.Text.Json.JsonSerializer.ReadFromSpan<System.__Canon>(System.ReadOnlySpan<byte> utf8Json, System.Text.Json.Serialization.Metadata.JsonTypeInfo<System.__Canon> jsonTypeInfo, int? actualByteCount) Line 145
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs(145)
System.Text.Json.dll!System.Text.Json.JsonSerializer.ReadFromSpan<Foo>(System.ReadOnlySpan<char> json, System.Text.Json.Serialization.Metadata.JsonTypeInfo<Foo> jsonTypeInfo) Line 400
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs(400)
System.Text.Json.dll!System.Text.Json.JsonSerializer.Deserialize<Foo>(string json, System.Text.Json.Serialization.Metadata.JsonTypeInfo<Foo> jsonTypeInfo) Line 197
at /_/src/runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs(197)
The regression seems to have been introduced in #115856