Skip to content

Commit fcae013

Browse files
Do not surface resolver exceptions when running ancestor type resolution (#85108)
1 parent 26f6d6c commit fcae013

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ internal JsonTypeInfo? AncestorPolymorphicType
639639
get
640640
{
641641
Debug.Assert(IsConfigured);
642+
Debug.Assert(Type != typeof(object));
642643

643644
if (!_isAncestorPolymorphicTypeResolved)
644645
{

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/PolymorphicTypeResolver.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ public static bool IsSupportedDerivedType(Type baseType, Type? derivedType) =>
252252
// First, walk up the class hierarchy for any supported types.
253253
for (Type? candidate = typeInfo.Type.BaseType; candidate != null; candidate = candidate.BaseType)
254254
{
255-
JsonTypeInfo? candidateInfo = typeInfo.Options.GetTypeInfoInternal(candidate, ensureNotNull: null);
255+
JsonTypeInfo? candidateInfo = ResolveAncestorTypeInfo(candidate, typeInfo.Options);
256256
if (candidateInfo?.PolymorphismOptions != null)
257257
{
258258
// stop on the first ancestor that has a match
@@ -264,7 +264,7 @@ public static bool IsSupportedDerivedType(Type baseType, Type? derivedType) =>
264264
// Now, walk the interface hierarchy for any polymorphic interface declarations.
265265
foreach (Type interfaceType in typeInfo.Type.GetInterfaces())
266266
{
267-
JsonTypeInfo? candidateInfo = typeInfo.Options.GetTypeInfoInternal(interfaceType, ensureNotNull: null);
267+
JsonTypeInfo? candidateInfo = ResolveAncestorTypeInfo(interfaceType, typeInfo.Options);
268268
if (candidateInfo?.PolymorphismOptions != null)
269269
{
270270
if (matchingResult != null)
@@ -294,6 +294,20 @@ public static bool IsSupportedDerivedType(Type baseType, Type? derivedType) =>
294294
}
295295

296296
return matchingResult;
297+
298+
static JsonTypeInfo? ResolveAncestorTypeInfo(Type type, JsonSerializerOptions options)
299+
{
300+
try
301+
{
302+
return options.GetTypeInfoInternal(type, ensureNotNull: null);
303+
}
304+
catch
305+
{
306+
// The resolver produced an exception when resolving the ancestor type.
307+
// Eat the exception and report no result instead.
308+
return null;
309+
}
310+
}
297311
}
298312

299313
/// <summary>

src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,36 @@ public async Task AnonymousType()
519519
Assert.Equal(Expected, json);
520520
}
521521

522+
[Fact]
523+
public async Task CustomResolverWithFailingAncestorType_DoesNotSurfaceException()
524+
{
525+
var options = new JsonSerializerOptions
526+
{
527+
TypeInfoResolver = new DefaultJsonTypeInfoResolver
528+
{
529+
Modifiers =
530+
{
531+
static typeInfo =>
532+
{
533+
if (typeInfo.Type == typeof(MyThing) ||
534+
typeInfo.Type == typeof(IList))
535+
{
536+
throw new InvalidOperationException("some latent custom resolution bug");
537+
}
538+
}
539+
}
540+
}
541+
};
542+
543+
object value = new MyDerivedThing { Number = 42 };
544+
string json = await Serializer.SerializeWrapper(value, options);
545+
Assert.Equal("""{"Number":42}""", json);
546+
547+
value = new int[] { 1, 2, 3 };
548+
json = await Serializer.SerializeWrapper(value, options);
549+
Assert.Equal("[1,2,3]", json);
550+
}
551+
522552
class MyClass
523553
{
524554
public string Value { get; set; }
@@ -535,6 +565,10 @@ class MyThing : IThing
535565
public int Number { get; set; }
536566
}
537567

568+
class MyDerivedThing : MyThing
569+
{
570+
}
571+
538572
class MyThingCollection : List<IThing> { }
539573

540574
class MyThingDictionary : Dictionary<string, IThing> { }

0 commit comments

Comments
 (0)