diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs index df4963e3b6ef2..975df8ae20227 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Text.Json.Serialization.Metadata; - namespace System.Text.Json.Serialization { public partial class JsonConverter @@ -58,7 +56,7 @@ public partial class JsonConverter } } - bool success = TryRead(ref reader, TypeToConvert, options, ref state, out T? value); + bool success = TryRead(ref reader, state.Current.JsonTypeInfo.Type, options, ref state, out T? value); if (success) { // Read any trailing whitespace. This will throw if JsonCommentHandling=Disallow. diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs index e61319e55caa1..cbf48b487946e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs @@ -278,5 +278,64 @@ public override void Write(Utf8JsonWriter writer, IRepro value, JsonSeri } } } + + [Fact] + public static void PolymorphicBaseClassConverter_IsPassedCorrectTypeToConvertParameter() + { + // Regression test for https://github.com/dotnet/runtime/issues/77173 + var options = new JsonSerializerOptions { Converters = { new PolymorphicBaseClassConverter() } }; + + // Sanity check -- returns converter for the base class. + JsonConverter converter = options.GetConverter(typeof(DerivedClass)); + Assert.IsAssignableFrom(converter); + + // Validate that the correct typeToConvert parameter is passed in all serialization contexts: + // 1. Typed root value. + // 2. Untyped root value (where the reported regression occured). + // 3. Nested values in POCOs, collections & dictionaries. + + DerivedClass result = JsonSerializer.Deserialize("{}", options); + Assert.IsType(result); + + object objResult = JsonSerializer.Deserialize("{}", typeof(DerivedClass), options); + Assert.IsType(objResult); + + PocoWithDerivedClassProperty pocoResult = JsonSerializer.Deserialize("""{"Value":{}}""", options); + Assert.IsType(pocoResult.Value); + + DerivedClass[] arrayResult = JsonSerializer.Deserialize("[{}]", options); + Assert.IsType(arrayResult[0]); + + Dictionary dictResult = JsonSerializer.Deserialize>("""{"Value":{}}""", options); + Assert.IsType(dictResult["Value"]); + } + + public class BaseClass + { } + + public class DerivedClass : BaseClass + { } + + public class PocoWithDerivedClassProperty + { + public DerivedClass Value { get; set; } + } + + public class PolymorphicBaseClassConverter : JsonConverter + { + public override bool CanConvert(Type typeToConvert) => typeof(BaseClass).IsAssignableFrom(typeToConvert); + + public override BaseClass? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Assert.Equal(typeof(DerivedClass), typeToConvert); + reader.Skip(); + return (BaseClass)Activator.CreateInstance(typeToConvert); + } + + public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } } }