<PackageReference Include="NJsonSchema" Version="10.7.0" />

DefaultReflectionService

The default reflection service implementation.
using Namotion.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using NJsonSchema.Annotations; using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace NJsonSchema.Generation { public class DefaultReflectionService : IReflectionService { public JsonTypeDescription GetDescription(ContextualType contextualType, JsonSchemaGeneratorSettings settings) { return GetDescription(contextualType, settings.DefaultReferenceTypeNullHandling, settings); } public virtual JsonTypeDescription GetDescription(ContextualType contextualType, ReferenceTypeNullHandling defaultReferenceTypeNullHandling, JsonSchemaGeneratorSettings settings) { Type type = contextualType.get_OriginalType(); bool isNullable = IsNullable(contextualType, defaultReferenceTypeNullHandling); JsonSchemaTypeAttribute attribute = contextualType.GetAttribute<JsonSchemaTypeAttribute>(); if (attribute != null) { type = attribute.Type; contextualType = ContextualTypeExtensions.ToContextualType(type); if (attribute.IsNullableRaw.HasValue) isNullable = attribute.IsNullableRaw.Value; } JsonSchemaAttribute attribute2 = contextualType.GetAttribute<JsonSchemaAttribute>(); if (attribute2 != null) { JsonObjectType jsonType = (attribute2.Type != 0) ? attribute2.Type : JsonObjectType.Object; string format = (!string.IsNullOrEmpty(attribute2.Format)) ? attribute2.Format : null; return JsonTypeDescription.Create(contextualType, jsonType, isNullable, format); } if (LegacyTypeExtensions.GetTypeInfo(type).IsEnum) { bool flag = IsStringEnum(contextualType, settings.ActualSerializerSettings); return JsonTypeDescription.CreateForEnumeration(contextualType, flag ? JsonObjectType.String : JsonObjectType.Integer, false); } if (type == typeof(short) || type == typeof(uint) || type == typeof(ushort)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, null); if (type == typeof(int)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, "int32"); if (type == typeof(long) || type == typeof(ulong)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, "int64"); if (type == typeof(double)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, "double"); if (type == typeof(float)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, "float"); if (type == typeof(decimal)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Number, false, "decimal"); if (type == typeof(bool)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Boolean, false, null); if (type == typeof(string) || type == typeof(Type)) return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, null); if (type == typeof(char)) return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, null); if (type == typeof(Guid)) return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "guid"); if (type == typeof(DateTime) || type == typeof(DateTimeOffset) || type.FullName == "NodaTime.OffsetDateTime" || type.FullName == "NodaTime.LocalDateTime" || type.FullName == "NodaTime.ZonedDateTime" || type.FullName == "NodaTime.Instant") return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "date-time"); if (type == typeof(TimeSpan) || type.FullName == "NodaTime.Duration") return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "duration"); if (type.FullName == "NodaTime.LocalDate" || type.FullName == "System.DateOnly") return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "date"); if (type.FullName == "NodaTime.LocalTime" || type.FullName == "System.TimeOnly") return JsonTypeDescription.Create(contextualType, JsonObjectType.String, false, "time"); if (type == typeof(Uri)) return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, "uri"); if (type == typeof(byte)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Integer, false, "byte"); if (type == typeof(byte[])) return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, "byte"); if (TypeExtensions.IsAssignableToTypeName(type, "JArray", 0)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Array, isNullable, null); if (TypeExtensions.IsAssignableToTypeName(type, "JToken", 0) || type.FullName == "System.Dynamic.ExpandoObject" || type.FullName == "System.Text.Json.JsonElement" || type == typeof(object)) return JsonTypeDescription.Create(contextualType, JsonObjectType.None, isNullable, null); if (IsBinary(contextualType)) { if (settings.SchemaType == SchemaType.Swagger2) return JsonTypeDescription.Create(contextualType, JsonObjectType.File, isNullable, null); return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, "binary"); } if (contextualType.get_IsNullableType()) { JsonTypeDescription description = GetDescription(contextualType.get_OriginalGenericArguments()[0], defaultReferenceTypeNullHandling, settings); description.IsNullable = true; return description; } JsonContract jsonContract = settings.ResolveContract(type); if (IsDictionaryType(contextualType) && jsonContract is JsonDictionaryContract) return JsonTypeDescription.CreateForDictionary(contextualType, JsonObjectType.Object, isNullable); if (IsIAsyncEnumerableType(contextualType) || (IsArrayType(contextualType) && jsonContract is JsonArrayContract)) return JsonTypeDescription.Create(contextualType, JsonObjectType.Array, isNullable, null); if (jsonContract is JsonStringContract) return JsonTypeDescription.Create(contextualType, JsonObjectType.String, isNullable, null); return JsonTypeDescription.Create(contextualType, JsonObjectType.Object, isNullable, null); } public virtual bool IsNullable(ContextualType contextualType, ReferenceTypeNullHandling defaultReferenceTypeNullHandling) { JsonPropertyAttribute contextAttribute = contextualType.GetContextAttribute<JsonPropertyAttribute>(); if (contextAttribute != null && contextAttribute.Required == Required.DisallowNull) return false; if (EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)contextualType.get_ContextAttributes(), "NotNullAttribute", 0) != null) return false; if (EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)contextualType.get_ContextAttributes(), "CanBeNullAttribute", 0) != null) return true; if ((int)contextualType.get_Nullability() != 0) return (int)contextualType.get_Nullability() == 2; if (!(contextualType.get_Type() != typeof(string)) || !contextualType.get_TypeInfo().IsValueType) return defaultReferenceTypeNullHandling != ReferenceTypeNullHandling.NotNull; return false; } public virtual bool IsStringEnum(ContextualType contextualType, JsonSerializerSettings serializerSettings) { if (!contextualType.get_TypeInfo().IsEnum) return false; if (!serializerSettings.Converters.OfType<StringEnumConverter>().Any()) return HasStringEnumConverter(contextualType); return true; } protected virtual bool IsBinary(ContextualType contextualType) { string typeName = contextualType.get_TypeName(); if (!(typeName == "IFormFile") && !TypeExtensions.IsAssignableToTypeName(contextualType, "HttpPostedFile", 0) && !TypeExtensions.IsAssignableToTypeName(contextualType, "HttpPostedFileBase", 0)) return contextualType.get_TypeInfo().GetInterfaces().Any((Type i) => i.Name == "IFormFile"); return true; } private bool IsIAsyncEnumerableType(ContextualType contextualType) { return contextualType.get_TypeName() == "IAsyncEnumerable`1"; } protected virtual bool IsArrayType(ContextualType contextualType) { if (IsDictionaryType(contextualType)) return false; if (contextualType.get_TypeName() == "ObservableCollection`1") return true; if (!contextualType.get_Type().IsArray) { if (Enumerable.Contains(contextualType.get_Type().GetInterfaces(), typeof(IEnumerable))) { if (!(contextualType.get_TypeInfo().BaseType == (Type)null)) return !Enumerable.Contains(LegacyTypeExtensions.GetTypeInfo(contextualType.get_TypeInfo().BaseType).GetInterfaces(), typeof(IEnumerable)); return true; } return false; } return true; } protected virtual bool IsDictionaryType(ContextualType contextualType) { if (contextualType.get_TypeName() == "IDictionary`2" || contextualType.get_TypeName() == "IReadOnlyDictionary`2") return true; if (Enumerable.Contains(contextualType.get_Type().GetInterfaces(), typeof(IDictionary))) { if (!(contextualType.get_TypeInfo().BaseType == (Type)null)) return !Enumerable.Contains(LegacyTypeExtensions.GetTypeInfo(contextualType.get_TypeInfo().BaseType).GetInterfaces(), typeof(IDictionary)); return true; } return false; } private bool HasStringEnumConverter(ContextualType contextualType) { IEnumerable<Attribute> attributes = contextualType.get_Attributes(); dynamic val = (attributes != null) ? attributes.FirstOrDefault((Attribute a) => a.GetType().Name == "JsonConverterAttribute") : null; dynamic val2 = val != null; if ((val2 ? false : true) ? val2 : (val2 & ObjectExtensions.HasProperty(val, "ConverterType"))) { Type type = (Type)val.ConverterType; if (type != (Type)null) { if (!TypeExtensions.IsAssignableToTypeName(type, "StringEnumConverter", 0)) return TypeExtensions.IsAssignableToTypeName(type, "System.Text.Json.Serialization.JsonStringEnumConverter", 1); return true; } } return false; } } }