Skip to content

Commit 12a44e9

Browse files
[release/7.0] Fix regression when serializing untyped polymorphic root-level custom converters. (#77388)
* Fix regression when serializing untyped polymorphic root-level custom converters. Fix #77173. * Update servicing version Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>
1 parent a3e1636 commit 12a44e9

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

src/libraries/System.Text.Json/src/System.Text.Json.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<NoWarn>CS8969</NoWarn>
99
<IncludeInternalObsoleteAttribute>true</IncludeInternalObsoleteAttribute>
1010
<IsPackable>true</IsPackable>
11+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
12+
<ServicingVersion>1</ServicingVersion>
1113
<!-- This library has been annotated to be AOT safe -->
1214
<EnableAOTAnalyzer>true</EnableAOTAnalyzer>
1315
<PackageDescription>Provides high-performance and low-allocating types that serialize objects to JavaScript Object Notation (JSON) text and deserialize JSON text to objects, with UTF-8 support built-in. Also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM), that is read-only, for random access of the JSON elements within a structured view of the data.

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.ReadCore.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Text.Json.Serialization.Metadata;
5-
64
namespace System.Text.Json.Serialization
75
{
86
public partial class JsonConverter<T>
@@ -58,7 +56,7 @@ public partial class JsonConverter<T>
5856
}
5957
}
6058

61-
bool success = TryRead(ref reader, TypeToConvert, options, ref state, out T? value);
59+
bool success = TryRead(ref reader, state.Current.JsonTypeInfo.Type, options, ref state, out T? value);
6260
if (success)
6361
{
6462
// Read any trailing whitespace. This will throw if JsonCommentHandling=Disallow.

src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Polymorphic.cs

+59
Original file line numberDiff line numberDiff line change
@@ -278,5 +278,64 @@ public override void Write(Utf8JsonWriter writer, IRepro<object> value, JsonSeri
278278
}
279279
}
280280
}
281+
282+
[Fact]
283+
public static void PolymorphicBaseClassConverter_IsPassedCorrectTypeToConvertParameter()
284+
{
285+
// Regression test for https://github.com/dotnet/runtime/issues/77173
286+
var options = new JsonSerializerOptions { Converters = { new PolymorphicBaseClassConverter() } };
287+
288+
// Sanity check -- returns converter for the base class.
289+
JsonConverter converter = options.GetConverter(typeof(DerivedClass));
290+
Assert.IsAssignableFrom<PolymorphicBaseClassConverter>(converter);
291+
292+
// Validate that the correct typeToConvert parameter is passed in all serialization contexts:
293+
// 1. Typed root value.
294+
// 2. Untyped root value (where the reported regression occured).
295+
// 3. Nested values in POCOs, collections & dictionaries.
296+
297+
DerivedClass result = JsonSerializer.Deserialize<DerivedClass>("{}", options);
298+
Assert.IsType<DerivedClass>(result);
299+
300+
object objResult = JsonSerializer.Deserialize("{}", typeof(DerivedClass), options);
301+
Assert.IsType<DerivedClass>(objResult);
302+
303+
PocoWithDerivedClassProperty pocoResult = JsonSerializer.Deserialize<PocoWithDerivedClassProperty>("""{"Value":{}}""", options);
304+
Assert.IsType<DerivedClass>(pocoResult.Value);
305+
306+
DerivedClass[] arrayResult = JsonSerializer.Deserialize<DerivedClass[]>("[{}]", options);
307+
Assert.IsType<DerivedClass>(arrayResult[0]);
308+
309+
Dictionary<string, DerivedClass> dictResult = JsonSerializer.Deserialize<Dictionary<string, DerivedClass>>("""{"Value":{}}""", options);
310+
Assert.IsType<DerivedClass>(dictResult["Value"]);
311+
}
312+
313+
public class BaseClass
314+
{ }
315+
316+
public class DerivedClass : BaseClass
317+
{ }
318+
319+
public class PocoWithDerivedClassProperty
320+
{
321+
public DerivedClass Value { get; set; }
322+
}
323+
324+
public class PolymorphicBaseClassConverter : JsonConverter<BaseClass>
325+
{
326+
public override bool CanConvert(Type typeToConvert) => typeof(BaseClass).IsAssignableFrom(typeToConvert);
327+
328+
public override BaseClass? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
329+
{
330+
Assert.Equal(typeof(DerivedClass), typeToConvert);
331+
reader.Skip();
332+
return (BaseClass)Activator.CreateInstance(typeToConvert);
333+
}
334+
335+
public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options)
336+
{
337+
throw new NotImplementedException();
338+
}
339+
}
281340
}
282341
}

0 commit comments

Comments
 (0)