diff --git a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs index 006c9c4e0e3ab..6cc6dbbf91e70 100644 --- a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs +++ b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs @@ -43,5 +43,24 @@ public static bool IsAssignableFromInternal(this Type type, Type from) private static bool HasJsonConstructorAttribute(ConstructorInfo constructorInfo) => constructorInfo.GetCustomAttribute() != null; + + public static TAttribute? GetUniqueCustomAttribute(this MemberInfo memberInfo, bool inherit) + where TAttribute : Attribute + { + object[] attributes = memberInfo.GetCustomAttributes(typeof(TAttribute), inherit); + + if (attributes.Length == 0) + { + return null; + } + + if (attributes.Length == 1) + { + return (TAttribute)attributes[0]; + } + + ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateAttribute(typeof(TAttribute), memberInfo); + return null; + } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs index 6ab528b639428..bdf26c36dfb9c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs @@ -32,9 +32,7 @@ public sealed partial class JsonSerializerOptions Debug.Assert(memberInfo.DeclaringType != null, "Properties and fields always have a declaring type."); JsonConverter? converter = null; - JsonConverterAttribute? converterAttribute = (JsonConverterAttribute?) - GetAttributeThatCanHaveMultiple(memberInfo.DeclaringType, typeof(JsonConverterAttribute), memberInfo); - + JsonConverterAttribute? converterAttribute = memberInfo.GetUniqueCustomAttribute(inherit: false); if (converterAttribute != null) { converter = GetConverterFromAttribute(converterAttribute, typeToConvert, memberInfo); @@ -176,9 +174,7 @@ private JsonConverter GetConverterFromOptionsOrReflectionConverter(Type typeToCo // Priority 2: Attempt to get converter from [JsonConverter] on the type being converted. if (converter == null) { - JsonConverterAttribute? converterAttribute = (JsonConverterAttribute?) - GetAttributeThatCanHaveMultiple(typeToConvert, typeof(JsonConverterAttribute)); - + JsonConverterAttribute? converterAttribute = typeToConvert.GetUniqueCustomAttribute(inherit: false); if (converterAttribute != null) { converter = GetConverterFromAttribute(converterAttribute, typeToConvert: typeToConvert, memberInfo: null); @@ -257,33 +253,5 @@ private JsonConverter GetConverterFromAttribute(JsonConverterAttribute converter return converter; } - - private static Attribute? GetAttributeThatCanHaveMultiple(Type classType, Type attributeType, MemberInfo memberInfo) - { - object[] attributes = memberInfo.GetCustomAttributes(attributeType, inherit: false); - return GetAttributeThatCanHaveMultiple(attributeType, classType, memberInfo, attributes); - } - - internal static Attribute? GetAttributeThatCanHaveMultiple(Type classType, Type attributeType) - { - object[] attributes = classType.GetCustomAttributes(attributeType, inherit: false); - return GetAttributeThatCanHaveMultiple(attributeType, classType, null, attributes); - } - - private static Attribute? GetAttributeThatCanHaveMultiple(Type attributeType, Type classType, MemberInfo? memberInfo, object[] attributes) - { - if (attributes.Length == 0) - { - return null; - } - - if (attributes.Length == 1) - { - return (Attribute)attributes[0]; - } - - ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateAttribute(attributeType, classType, memberInfo); - return default; - } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs index 3112df742dd96..22f322478ec60 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs @@ -212,9 +212,7 @@ private void CacheMember( private static JsonNumberHandling? GetNumberHandlingForType(Type type) { - var numberHandlingAttribute = - (JsonNumberHandlingAttribute?)JsonSerializerOptions.GetAttributeThatCanHaveMultiple(type, typeof(JsonNumberHandlingAttribute)); - + JsonNumberHandlingAttribute? numberHandlingAttribute = type.GetUniqueCustomAttribute(inherit: false); return numberHandlingAttribute?.Handling; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index 88f72117763ba..b65ab991d8897 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -398,14 +398,9 @@ public static void AddJsonExceptionInformation(ref WriteStack state, JsonExcepti } [DoesNotReturn] - public static void ThrowInvalidOperationException_SerializationDuplicateAttribute(Type attribute, Type classType, MemberInfo? memberInfo) + public static void ThrowInvalidOperationException_SerializationDuplicateAttribute(Type attribute, MemberInfo memberInfo) { - string location = classType.ToString(); - if (memberInfo != null) - { - location += $".{memberInfo.Name}"; - } - + string location = memberInfo is Type type ? type.ToString() : $"{memberInfo.DeclaringType}.{memberInfo.Name}"; throw new InvalidOperationException(SR.Format(SR.SerializationDuplicateAttribute, attribute, location)); }