Skip to content

Commit

Permalink
[release/7.0] Fix regression when serializing untyped polymorphic roo…
Browse files Browse the repository at this point in the history
…t-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>
  • Loading branch information
github-actions[bot] and eiriktsarpalis authored Nov 3, 2022
1 parent a3e1636 commit 12a44e9
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/libraries/System.Text.Json/src/System.Text.Json.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<NoWarn>CS8969</NoWarn>
<IncludeInternalObsoleteAttribute>true</IncludeInternalObsoleteAttribute>
<IsPackable>true</IsPackable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<ServicingVersion>1</ServicingVersion>
<!-- This library has been annotated to be AOT safe -->
<EnableAOTAnalyzer>true</EnableAOTAnalyzer>
<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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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<T>
Expand Down Expand Up @@ -58,7 +56,7 @@ public partial class JsonConverter<T>
}
}

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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,64 @@ public override void Write(Utf8JsonWriter writer, IRepro<object> 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<PolymorphicBaseClassConverter>(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<DerivedClass>("{}", options);
Assert.IsType<DerivedClass>(result);

object objResult = JsonSerializer.Deserialize("{}", typeof(DerivedClass), options);
Assert.IsType<DerivedClass>(objResult);

PocoWithDerivedClassProperty pocoResult = JsonSerializer.Deserialize<PocoWithDerivedClassProperty>("""{"Value":{}}""", options);
Assert.IsType<DerivedClass>(pocoResult.Value);

DerivedClass[] arrayResult = JsonSerializer.Deserialize<DerivedClass[]>("[{}]", options);
Assert.IsType<DerivedClass>(arrayResult[0]);

Dictionary<string, DerivedClass> dictResult = JsonSerializer.Deserialize<Dictionary<string, DerivedClass>>("""{"Value":{}}""", options);
Assert.IsType<DerivedClass>(dictResult["Value"]);
}

public class BaseClass
{ }

public class DerivedClass : BaseClass
{ }

public class PocoWithDerivedClassProperty
{
public DerivedClass Value { get; set; }
}

public class PolymorphicBaseClassConverter : JsonConverter<BaseClass>
{
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();
}
}
}
}

0 comments on commit 12a44e9

Please sign in to comment.