From 2a7302e37acf4cdc70ab6ff0d96068ab0ad79bbc Mon Sep 17 00:00:00 2001 From: Xeron <2398003522@qq.com> Date: Mon, 6 Apr 2026 15:22:20 +0800 Subject: [PATCH 1/3] Fix JsonException message property type info in class parameterized constructor --- .../src/System/Text/Json/ThrowHelper.Serialization.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index f23a02a036e282..afccfa57946fe1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -540,7 +540,9 @@ public static void AddJsonExceptionInformation(scoped ref ReadStack state, in Ut if (string.IsNullOrEmpty(message)) { // Use a default message. - Type propertyType = state.Current.JsonPropertyInfo?.PropertyType ?? state.Current.JsonTypeInfo.Type; + Type propertyType = state.Current.JsonPropertyInfo?.PropertyType ?? + state.Current.CtorArgumentState?.JsonParameterInfo?.ParameterType ?? + state.Current.JsonTypeInfo.Type; message = SR.Format(SR.DeserializeUnableToConvertValue, propertyType); ex.AppendPathInformation = true; } From 970f2c7b6ef805020196f85a147909e4d4575185 Mon Sep 17 00:00:00 2001 From: Xeron <2398003522@qq.com> Date: Sun, 12 Apr 2026 10:47:40 +0800 Subject: [PATCH 2/3] Add regression test for JsonException message with parameterized constructors This test verifies that when deserialization fails for classes with parameterized constructors, the JsonException message reports the correct property type (e.g., System.String) rather than the declaring class type. Covers both parameterized classes and records to ensure the fix in ThrowHelper.Serialization.cs works correctly across different scenarios. --- .../ConstructorTests.Exceptions.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs index 9f2db72f2d9987..abcf7e1ecd9f60 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs @@ -350,5 +350,31 @@ public ClassWithInvalidDictionary(Dictionary unsupportedDictiona UnsupportedDictionary = unsupportedDictionary; } } + + [Fact] + public async Task ParameterizedConstructor_ExceptionMessage_ReportsPropertyType() + { + // Regression test: classes with parameterized constructors should report the + // property type (System.String), not the declaring class type, in the JsonException message. + // https://github.com/dotnet/runtime/pull/126575 + JsonException e; + + e = await Assert.ThrowsAsync(() => + Serializer.DeserializeWrapper("""{"Text":{}}""")); + Assert.Contains("System.String", e.Message); + Assert.DoesNotContain(nameof(ParameterizedClass_WithStringProperty), e.Message); + + e = await Assert.ThrowsAsync(() => + Serializer.DeserializeWrapper("""{"Text":{}}""")); + Assert.Contains("System.String", e.Message); + Assert.DoesNotContain(nameof(ParameterizedRecord_WithStringProperty), e.Message); + } + + private class ParameterizedClass_WithStringProperty(string text) + { + public string Text { get; set; } = text; + } + + private record ParameterizedRecord_WithStringProperty(string Text); } } From a14616cbaef8abddbcad61d3570a05eb1bfa69ec Mon Sep 17 00:00:00 2001 From: Xeron <2398003522@qq.com> Date: Sun, 12 Apr 2026 14:03:32 +0800 Subject: [PATCH 3/3] Fix source generation tests for parameterized constructor exception message test Make test classes public and register them in source generation contexts to fix compilation errors in System.Text.Json.SourceGeneration.Tests. The test classes need to be public (not private) so they can be referenced by the JsonSerializable attributes in the source generation test contexts. --- .../Common/ConstructorTests/ConstructorTests.Exceptions.cs | 4 ++-- .../Serialization/ConstructorTests.cs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs index abcf7e1ecd9f60..c80bf5f3a101f4 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs @@ -370,11 +370,11 @@ public async Task ParameterizedConstructor_ExceptionMessage_ReportsPropertyType( Assert.DoesNotContain(nameof(ParameterizedRecord_WithStringProperty), e.Message); } - private class ParameterizedClass_WithStringProperty(string text) + public class ParameterizedClass_WithStringProperty(string text) { public string Text { get; set; } = text; } - private record ParameterizedRecord_WithStringProperty(string Text); + public record ParameterizedRecord_WithStringProperty(string Text); } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs index 8aae01fb6ddf30..1f1726d2f5fe43 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs @@ -177,6 +177,8 @@ protected ConstructorTests_Metadata(JsonSerializerWrapper stringWrapper) [JsonSerializable(typeof(TypeWith_RefReadonlyParameter_Primitive))] [JsonSerializable(typeof(TypeWith_RefReadonlyParameter_Struct))] [JsonSerializable(typeof(TypeWith_RefReadonlyParameter_ReferenceType))] + [JsonSerializable(typeof(ParameterizedClass_WithStringProperty))] + [JsonSerializable(typeof(ParameterizedRecord_WithStringProperty))] internal sealed partial class ConstructorTestsContext_Metadata : JsonSerializerContext { } @@ -349,6 +351,8 @@ public ConstructorTests_Default(JsonSerializerWrapper jsonSerializer) : base(jso [JsonSerializable(typeof(TypeWith_RefReadonlyParameter_Primitive))] [JsonSerializable(typeof(TypeWith_RefReadonlyParameter_Struct))] [JsonSerializable(typeof(TypeWith_RefReadonlyParameter_ReferenceType))] + [JsonSerializable(typeof(ParameterizedClass_WithStringProperty))] + [JsonSerializable(typeof(ParameterizedRecord_WithStringProperty))] internal sealed partial class ConstructorTestsContext_Default : JsonSerializerContext { }