diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj
index fc5c8ce5591c9f..b915e3ec37bf33 100644
--- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj
+++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj
@@ -142,6 +142,7 @@
+
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/GenericMethodHolder.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/GenericMethodHolder.cs
new file mode 100644
index 00000000000000..ef8e362e1a695b
--- /dev/null
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/GenericMethodHolder.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Text.Json.Serialization
+{
+ ///
+ /// Allows virtual dispatch to GenericMethodHolder{T}.
+ ///
+ internal abstract class GenericMethodHolder
+ {
+ ///
+ /// Returns true if contains only default values.
+ ///
+ public abstract bool IsDefaultValue(object value);
+ }
+
+ ///
+ /// Generic methods for {T}.
+ ///
+ internal sealed class GenericMethodHolder : GenericMethodHolder
+ {
+ public override bool IsDefaultValue(object value)
+ {
+ // For performance, we only want to call this method for non-nullable value types.
+ // Nullable types should be checked againt 'null' before calling this method.
+ Debug.Assert(Nullable.GetUnderlyingType(value.GetType()) == null);
+
+ return EqualityComparer.Default.Equals(default, (T)value);
+ }
+ }
+}
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs
index 6f523b19b8294c..8f2f195517ecbf 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs
@@ -79,6 +79,24 @@ public JsonClassInfo? ElementClassInfo
///
public JsonPropertyInfo PropertyInfoForClassInfo { get; private set; }
+ private GenericMethodHolder? _genericMethods;
+ ///
+ /// Returns a helper class used when generic methods need to be invoked on Type.
+ ///
+ public GenericMethodHolder GenericMethods
+ {
+ get
+ {
+ if (_genericMethods == null)
+ {
+ Type runtimePropertyClass = typeof(GenericMethodHolder<>).MakeGenericType(new Type[] { Type })!;
+ _genericMethods = (GenericMethodHolder)Activator.CreateInstance(runtimePropertyClass)!;
+ }
+
+ return _genericMethods;
+ }
+ }
+
public JsonClassInfo(Type type, JsonSerializerOptions options)
{
Type = type;
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs
index cfb6e69833408d..2552f30a5a378d 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs
@@ -12,6 +12,7 @@ namespace System.Text.Json
internal abstract class JsonPropertyInfo
{
public static readonly JsonPropertyInfo s_missingProperty = GetPropertyPlaceholder();
+ public static readonly Type s_NullableType = typeof(Nullable<>);
private JsonClassInfo? _runtimeClassInfo;
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs
index 48f952a8a19a78..98482c8906c344 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoOfT.cs
@@ -23,6 +23,11 @@ internal sealed class JsonPropertyInfo : JsonPropertyInfo
///
private bool _converterIsExternalAndPolymorphic;
+ // Since a converter's TypeToConvert (which is the T value in this type) can be different than
+ // the property's type, we track that and whether the property type can be null.
+ private bool _propertyTypeEqualsTypeToConvert;
+ private bool _propertyTypeCanBeNull;
+
public Func