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

JsonSchemaGenerator

public class JsonSchemaGenerator
Generates a JsonSchema object for a given type.
using Namotion.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NJsonSchema.Annotations; using NJsonSchema.Converters; using NJsonSchema.Generation.TypeMappers; using NJsonSchema.Infrastructure; using NJsonSchema.References; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace NJsonSchema.Generation { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class JsonSchemaGenerator { [System.Runtime.CompilerServices.Nullable(0)] private sealed class SystemTextJsonInheritanceWrapper { private readonly dynamic[] _jsonDerivedTypeAttributes; public string DiscriminatorName { get; } public SystemTextJsonInheritanceWrapper(string discriminatorName, dynamic[] jsonDerivedTypeAttributes) { DiscriminatorName = discriminatorName; _jsonDerivedTypeAttributes = jsonDerivedTypeAttributes; } public string GetDiscriminatorValue(Type type) { dynamic val = _jsonDerivedTypeAttributes.FirstOrDefault((dynamic a) => (byte)(a.DerivedType == type) != 0)?.TypeDiscriminator?.ToString(); if ((object)val == null) throw new InvalidOperationException("Discriminator value for " + type.FullName + " not found."); return (string)val; } } private static readonly Dictionary<string, string> DataTypeFormats = new Dictionary<string, string> { { "DateTime", "date-time" }, { "Date", "date" }, { "Time", "time" }, { "EmailAddress", "email" }, { "PhoneNumber", "phone" }, { "Url", "uri" } }; public JsonSchemaGeneratorSettings Settings { get; } public JsonSchemaGenerator(JsonSchemaGeneratorSettings settings) { Settings = settings; } public static JsonSchema FromType<[System.Runtime.CompilerServices.Nullable(2)] TType>(JsonSchemaGeneratorSettings settings) { JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(settings); return jsonSchemaGenerator.Generate(typeof(TType)); } public static JsonSchema FromType(Type type, JsonSchemaGeneratorSettings settings) { JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(settings); return jsonSchemaGenerator.Generate(type); } public JsonSchema Generate(Type type) { JsonSchema jsonSchema = new JsonSchema(); JsonSchemaResolver schemaResolver = new JsonSchemaResolver(jsonSchema, Settings); Generate(jsonSchema, ContextualTypeExtensions.ToContextualType(type), schemaResolver); return jsonSchema; } public JsonSchema Generate(Type type, JsonSchemaResolver schemaResolver) { return Generate<JsonSchema>(type, schemaResolver); } public TSchemaType Generate<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(Type type, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { return Generate<TSchemaType>(ContextualTypeExtensions.ToContextualType(type), schemaResolver); } public JsonSchema Generate(ContextualType contextualType, JsonSchemaResolver schemaResolver) { return Generate<JsonSchema>(contextualType, schemaResolver); } public TSchemaType Generate<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(ContextualType contextualType, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { TSchemaType val = new TSchemaType(); Generate(val, contextualType, schemaResolver); return val; } public void Generate<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(TSchemaType schema, Type type, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { Generate(schema, ContextualTypeExtensions.ToContextualType(type), schemaResolver); } public virtual void Generate<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { JsonTypeDescription description = Settings.ReflectionService.GetDescription(contextualType, Settings); ApplyTypeExtensionDataAttributes(schema, contextualType); if (TryHandleSpecialTypes(schema, description.ContextualType, schemaResolver)) ApplySchemaProcessors(schema, description.ContextualType, schemaResolver); else { if (schemaResolver.RootObject == schema) schema.Title = Settings.SchemaNameGenerator.Generate(description.ContextualType.get_Type()); if (description.Type.IsObject()) { if (description.IsDictionary) GenerateDictionary(schema, description, schemaResolver); else if (schemaResolver.HasSchema(description.ContextualType.get_Type(), false)) { ((JsonReferenceBase<JsonSchema>)schema).Reference = schemaResolver.GetSchema(description.ContextualType.get_Type(), false); } else if (schema.GetType() == typeof(JsonSchema)) { GenerateObject(schema, description, schemaResolver); } else { ((JsonReferenceBase<JsonSchema>)schema).Reference = Generate(description.ContextualType, schemaResolver); } } else if (description.IsEnum) { GenerateEnum(schema, description, schemaResolver); } else if (description.Type.IsArray()) { GenerateArray(schema, description, schemaResolver); } else { description.ApplyType(schema); } if ((object)contextualType != (object)description.ContextualType) ApplySchemaProcessors(schema, description.ContextualType, schemaResolver); ApplySchemaProcessors(schema, contextualType, schemaResolver); } } public TSchemaType GenerateWithReference<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(ContextualType contextualType, JsonSchemaResolver schemaResolver, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 1 })] Action<TSchemaType, JsonSchema> transformation = null) where TSchemaType : JsonSchema, new { return GenerateWithReferenceAndNullability(contextualType, false, schemaResolver, transformation); } public TSchemaType GenerateWithReferenceAndNullability<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(ContextualType contextualType, JsonSchemaResolver schemaResolver, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 1 })] Action<TSchemaType, JsonSchema> transformation = null) where TSchemaType : JsonSchema, new { JsonTypeDescription description = Settings.ReflectionService.GetDescription(contextualType, Settings); return GenerateWithReferenceAndNullability(contextualType, description.IsNullable, schemaResolver, transformation); } public virtual TSchemaType GenerateWithReferenceAndNullability<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(ContextualType contextualType, bool isNullable, JsonSchemaResolver schemaResolver, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 1 })] Action<TSchemaType, JsonSchema> transformation = null) where TSchemaType : JsonSchema, new { JsonTypeDescription description = Settings.ReflectionService.GetDescription(contextualType, Settings); JsonSchema jsonSchema; if (!description.RequiresSchemaReference(Settings.TypeMappers)) { TSchemaType val = Generate<TSchemaType>(description.ContextualType, schemaResolver); if (!val.HasReference) { transformation?.Invoke(val, (JsonSchema)val); if (isNullable) { if (Settings.SchemaType == SchemaType.JsonSchema) { if ((int)val.Type == 0) { ((Collection<JsonSchema>)val._oneOf).Add(new JsonSchema { Type = 0 }); ((Collection<JsonSchema>)val._oneOf).Add(new JsonSchema { Type = 8 }); } else val.Type |= 8; } else if (Settings.SchemaType == SchemaType.OpenApi3 || Settings.GenerateCustomNullableProperties) { val.IsNullableRaw = true; } } return val; } jsonSchema = val.ActualSchema; } else jsonSchema = Generate<JsonSchema>(description.ContextualType, schemaResolver); TSchemaType val2 = new TSchemaType(); transformation?.Invoke(val2, jsonSchema); if (isNullable) { if (Settings.SchemaType == SchemaType.JsonSchema) ((Collection<JsonSchema>)val2._oneOf).Add(new JsonSchema { Type = 8 }); else if (Settings.SchemaType == SchemaType.OpenApi3 || Settings.GenerateCustomNullableProperties) { val2.IsNullableRaw = true; } } int num; if (!Settings.AllowReferencesWithProperties) { JObject jObject = JsonConvert.DeserializeObject<JObject>(JsonConvert.SerializeObject(val2)); if (jObject == null) num = 0; else { IEnumerable<JProperty> enumerable = jObject.Properties(); bool? nullable = (enumerable != null) ? new bool?(enumerable.Any()) : null; bool flag = false; num = (((nullable.GetValueOrDefault() == flag) & nullable.HasValue) ? 1 : 0); } } else num = 1; if (num != 0 && ((Collection<JsonSchema>)val2._oneOf).Count == 0) ((JsonReferenceBase<JsonSchema>)val2).Reference = jsonSchema.ActualSchema; else if (Settings.SchemaType != SchemaType.Swagger2) { ((Collection<JsonSchema>)val2._oneOf).Add(new JsonSchema { Reference = jsonSchema.ActualSchema }); } else { ((Collection<JsonSchema>)val2._allOf).Add(new JsonSchema { Reference = jsonSchema.ActualSchema }); } return val2; } public virtual void ApplyDataAnnotations(JsonSchema schema, JsonTypeDescription typeDescription) { ContextualType contextualType = typeDescription.ContextualType; Attribute[] array = AttributeExtensions.GetContextAttributes(contextualType, true).ToArray(); dynamic val = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "System.ComponentModel.DataAnnotations.DisplayAttribute", 1); if (val != null) { dynamic val2 = val.GetName(); if (val2 != null) schema.Title = (string)val2; } dynamic val3 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "System.ComponentModel.DefaultValueAttribute", 1); if (val3 != null) { if (typeDescription.IsEnum && typeDescription.Type.IsString()) schema.Default = (object)val3.Value?.ToString(); else schema.Default = (object)val3.Value; } dynamic val4 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "System.ComponentModel.DataAnnotations.RegularExpressionAttribute", 1); if (val4 != null) { if (typeDescription.IsDictionary) { if (schema.AdditionalPropertiesSchema == null) { JsonSchema jsonSchema2 = schema.AdditionalPropertiesSchema = new JsonSchema(); } schema.AdditionalPropertiesSchema.Pattern = (string)val4.Pattern; } else schema.Pattern = (string)val4.Pattern; } JsonObjectType type = typeDescription.Type; if (((int)type == 4 || (int)type == 16) ? true : false) { ApplyRangeAttribute(schema, array); MultipleOfAttribute contextAttribute = AttributeExtensions.GetContextAttribute<MultipleOfAttribute>(contextualType, true); if (contextAttribute != null) schema.MultipleOf = contextAttribute.get_MultipleOf(); } object obj = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "System.ComponentModel.DataAnnotations.MinLengthAttribute", 1); if (((dynamic)obj)?.Length != null) { if ((int)typeDescription.Type == 64) schema.MinLength = (int?)((dynamic)obj)?.Length; else if ((int)typeDescription.Type == 1) { schema.MinItems = (int)((dynamic)obj)?.Length; } } object obj2 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "System.ComponentModel.DataAnnotations.MaxLengthAttribute", 1); if (((dynamic)obj2)?.Length != null) { if ((int)typeDescription.Type == 64) schema.MaxLength = (int?)((dynamic)obj2)?.Length; else if ((int)typeDescription.Type == 1) { schema.MaxItems = (int)((dynamic)obj2)?.Length; } } dynamic val5 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "System.ComponentModel.DataAnnotations.StringLengthAttribute", 1); if ((val5 != null) && (int)typeDescription.Type == 64) { schema.MinLength = (int?)val5.MinimumLength; schema.MaxLength = (int?)val5.MaximumLength; } dynamic val6 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "System.ComponentModel.DataAnnotations.DataTypeAttribute", 1); if (val6 != null) { dynamic val7 = val6.DataType.ToString(); string format = default(string); if (DataTypeFormats.TryGetValue(val7, out format)) schema.Format = format; } } [System.Runtime.CompilerServices.NullableContext(2)] public virtual object ConvertDefaultValue([System.Runtime.CompilerServices.Nullable(1)] ContextualType type, object defaultValue) { if (defaultValue != null && defaultValue.GetType().GetTypeInfo().IsEnum) { if (Settings.ReflectionService.IsStringEnum(type, Settings)) return defaultValue?.ToString(); return (int)defaultValue; } return defaultValue; } [return: System.Runtime.CompilerServices.Nullable(2)] public virtual object GenerateExample(ContextualType type) { if (Settings.GenerateExamples && Settings.UseXmlDocumentation) try { string xmlDocsTag = XmlDocsExtensions.GetXmlDocsTag(type, "example", Settings.GetXmlDocsOptions()); return GenerateExample(xmlDocsTag); } catch { return null; } return null; } [return: System.Runtime.CompilerServices.Nullable(2)] public virtual object GenerateExample(ContextualAccessorInfo accessorInfo) { if (Settings.GenerateExamples && Settings.UseXmlDocumentation) try { string xmlDocsTag = XmlDocsExtensions.GetXmlDocsTag(accessorInfo, "example", Settings.GetXmlDocsOptions()); return GenerateExample(xmlDocsTag); } catch { return null; } return null; } [return: System.Runtime.CompilerServices.Nullable(2)] private static object GenerateExample(string xmlDocs) { try { return (!string.IsNullOrEmpty(xmlDocs)) ? JsonConvert.DeserializeObject<JToken>(xmlDocs) : null; } catch { return xmlDocs; } } protected virtual void GenerateObject(JsonSchema schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver) { Type type = typeDescription.ContextualType.get_Type(); schemaResolver.AddSchema(type, false, schema); JsonSchema schema2 = schema; JsonSchema jsonSchema = GenerateInheritance(typeDescription.ContextualType, schema, schemaResolver); if (jsonSchema != null) schema = jsonSchema; else { Settings.ReflectionService.GenerateProperties(schema, typeDescription.ContextualType, Settings, this, schemaResolver); ApplyAdditionalProperties(schema, type, schemaResolver); } if (!schema.Type.IsArray()) typeDescription.ApplyType(schema); schema.Description = TypeExtensions.GetDescription(ContextualTypeExtensions.ToCachedType(type), (IXmlDocsSettings)Settings); schema.Example = this.GenerateExample(ContextualTypeExtensions.ToContextualType(type)); dynamic val = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<object>((IEnumerable<object>)type.GetTypeInfo().GetCustomAttributes(false), "System.ObsoleteAttribute", 1); if (val != null) { schema.IsDeprecated = true; schema.DeprecatedMessage = (string)val.Message; } if (Settings.GetActualGenerateAbstractSchema(type)) schema.IsAbstract = type.GetTypeInfo().IsAbstract; GenerateInheritanceDiscriminator(type, schema2, schema); GenerateKnownTypes(type, schemaResolver); if (Settings.GenerateXmlObjects) schema.GenerateXmlObjectForType(type); } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] public virtual string[] GetTypeProperties(Type type) { if (type == typeof(Exception)) return new string[4] { "InnerException", "Message", "Source", "StackTrace" }; return null; } protected virtual void GenerateArray<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(TSchemaType schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { ContextualType contextualType = typeDescription.ContextualType; typeDescription.ApplyType(schema); JsonSchemaAttribute contextOrTypeAttribute = AttributeExtensions.GetContextOrTypeAttribute<JsonSchemaAttribute>(contextualType, true); object obj; if (contextOrTypeAttribute == null) obj = null; else { Type arrayItem = contextOrTypeAttribute.get_ArrayItem(); obj = (((object)arrayItem != null) ? ((object)ContextualTypeExtensions.ToContextualType(arrayItem)) : null); } if (obj == null) { ContextualType enumerableItemType = contextualType.get_EnumerableItemType(); obj = (object)enumerableItemType; if ((int)enumerableItemType == 0) obj = contextualType.get_GenericArguments().FirstOrDefault(); } ContextualType itemType = obj; if (itemType != null) { bool isNullable = AttributeExtensions.IsContextAttributeDefined<ItemsCanBeNullAttribute>(contextualType, true) || (int)itemType.get_Nullability() == 2; schema.Item = GenerateWithReferenceAndNullability(itemType, isNullable, schemaResolver, delegate(JsonSchema itemSchema, JsonSchema typeSchema) { if (Settings.GenerateXmlObjects) itemSchema.GenerateXmlObjectForItemType(itemType); }); if (Settings.GenerateXmlObjects) schema.GenerateXmlObjectForArrayType(); } else schema.Item = JsonSchema.CreateAnySchema(); Attribute[] array = AttributeExtensions.GetContextAttributes(contextualType, true).ToArray(); dynamic val = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "MinLengthAttribute", 0); dynamic val2 = val != null; if ((val2 ? false : true) ? val2 : (val2 & ObjectExtensions.HasProperty(val, "Length"))) schema.MinItems = (int)val?.Length; dynamic val3 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "MaxLengthAttribute", 0); val2 = (val3 != null); if ((val2 ? false : true) ? val2 : (val2 & ObjectExtensions.HasProperty(val3, "Length"))) schema.MaxItems = (int)val3?.Length; } protected virtual void GenerateDictionary<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(TSchemaType schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { ContextualType contextualType = typeDescription.ContextualType; typeDescription.ApplyType(schema); ContextualType[] genericArguments = contextualType.get_GenericArguments(); ContextualType val = (genericArguments.Length == 2) ? ((object)genericArguments[0]) : ((object)ContextualTypeExtensions.ToContextualType(typeof(string))); if (val.get_OriginalType().GetTypeInfo().IsEnum) schema.DictionaryKey = GenerateWithReference<JsonSchema>(val, schemaResolver, null); ContextualType val2 = (genericArguments.Length == 2) ? ((object)genericArguments[1]) : ((object)ContextualTypeExtensions.ToContextualType(typeof(object))); Attribute[] array = AttributeExtensions.GetContextAttributes(contextualType, true).ToArray(); IEnumerable<JsonSchemaPatternPropertiesAttribute> enumerable = array.OfType<JsonSchemaPatternPropertiesAttribute>(); if (enumerable.Any()) { schema.AllowAdditionalProperties = false; foreach (JsonSchemaPatternPropertiesAttribute item in enumerable) { Type type = item.get_Type(); JsonSchemaProperty value = GenerateDictionaryValueSchema<JsonSchemaProperty>(schemaResolver, ((object)(((object)type != null) ? ContextualTypeExtensions.ToContextualType(type) : null)) ?? ((object)val2)); schema.PatternProperties.Add(item.get_RegularExpression(), value); } } else { schema.AdditionalPropertiesSchema = GenerateDictionaryValueSchema<JsonSchema>(schemaResolver, val2); schema.AllowAdditionalProperties = true; } dynamic val3 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "MinLengthAttribute", 0); dynamic val4 = val3 != null; if ((val4 ? false : true) ? val4 : (val4 & ObjectExtensions.HasProperty(val3, "Length"))) schema.MinProperties = (int)val3?.Length; dynamic val5 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>((IEnumerable<Attribute>)array, "MaxLengthAttribute", 0); val4 = (val5 != null); if ((val4 ? false : true) ? val4 : (val4 & ObjectExtensions.HasProperty(val5, "Length"))) schema.MaxProperties = (int)val5?.Length; } protected virtual void GenerateEnum(JsonSchema schema, JsonTypeDescription typeDescription) { ContextualType contextualType = typeDescription.ContextualType; schema.Type = typeDescription.Type; schema.Enumeration.Clear(); schema.EnumerationNames.Clear(); schema.IsFlagEnumerable = AttributeExtensions.IsAttributeDefined<FlagsAttribute>(contextualType, true); Func<object, string> func = null; Type underlyingType = Enum.GetUnderlyingType(contextualType.get_Type()); string[] names = Enum.GetNames(contextualType.get_Type()); foreach (string text in names) { if ((int)typeDescription.Type == 4) { object item = Convert.ChangeType(Enum.Parse(contextualType.get_Type(), text), underlyingType, CultureInfo.InvariantCulture); schema.Enumeration.Add(item); } else { FieldInfo runtimeField = contextualType.get_Type().GetRuntimeField(text); EnumMemberAttribute enumMemberAttribute = ((object)runtimeField != null) ? runtimeField.GetCustomAttribute<EnumMemberAttribute>() : null; if (enumMemberAttribute != null && !string.IsNullOrEmpty(enumMemberAttribute.Value)) schema.Enumeration.Add(enumMemberAttribute.Value); else { if (func == null) func = Settings.ReflectionService.GetEnumValueConverter(Settings); object arg = Enum.Parse(contextualType.get_Type(), text); schema.Enumeration.Add(func(arg)); } } schema.EnumerationNames.Add(text); } if ((int)typeDescription.Type == 4 && Settings.GenerateEnumMappingDescription) schema.Description = (schema.Description + "\n\n" + string.Join("\n", schema.Enumeration.Select((object e, int i) => e?.ToString() + " = " + schema.EnumerationNames[i]))).Trim(); } private TSchema GenerateDictionaryValueSchema<[System.Runtime.CompilerServices.Nullable(0)] TSchema>(JsonSchemaResolver schemaResolver, ContextualType valueType) where TSchema : JsonSchema, new { if (valueType.get_OriginalType() == typeof(object)) { TSchema val = new TSchema(); if (Settings.SchemaType == SchemaType.Swagger2) val.AllowAdditionalProperties = false; return val; } JsonTypeDescription description = Settings.ReflectionService.GetDescription(valueType, Settings.DefaultDictionaryValueReferenceTypeNullHandling, Settings); bool isNullable = AttributeExtensions.IsContextAttributeDefined<ItemsCanBeNullAttribute>(valueType, true) || description.IsNullable; return GenerateWithReferenceAndNullability<TSchema>(valueType, isNullable, schemaResolver, null); } private void ApplyAdditionalProperties<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(TSchemaType schema, Type type, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { ContextualPropertyInfo val = ((IEnumerable<ContextualPropertyInfo>)ContextualTypeExtensions.GetContextualProperties(type)).FirstOrDefault((Func<ContextualPropertyInfo, bool>)((ContextualPropertyInfo p) => Enumerable.Any<Attribute>(AttributeExtensions.GetAttributes(p, true), (Func<Attribute, bool>)((Attribute a) => TypeExtensions.IsAssignableToTypeName(a.GetType(), "JsonExtensionDataAttribute", 0))))); if (val != null) { ContextualType[] genericArguments = val.get_AccessorType().get_GenericArguments(); ContextualType contextualType = (genericArguments.Length == 2) ? ((object)genericArguments[1]) : ((object)ContextualTypeExtensions.ToContextualType(typeof(object))); schema.AdditionalPropertiesSchema = GenerateWithReferenceAndNullability<JsonSchema>(contextualType, schemaResolver, null); } else schema.AllowAdditionalProperties = Settings.AlwaysAllowAdditionalObjectProperties; } private void ApplySchemaProcessors(JsonSchema schema, ContextualType contextualType, JsonSchemaResolver schemaResolver) { SchemaProcessorContext schemaProcessorContext = new SchemaProcessorContext(contextualType, schema, schemaResolver, this, Settings); foreach (ISchemaProcessor schemaProcessor in Settings.SchemaProcessors) { schemaProcessor.Process(schemaProcessorContext); } IEnumerable<Attribute> assignableToTypeName = EnumerableExtensions.GetAssignableToTypeName<Attribute>(AttributeExtensions.GetAttributes(contextualType, true), "JsonSchemaProcessorAttribute", 0); foreach (dynamic item in assignableToTypeName) { dynamic val = Activator.CreateInstance(item.Type, item.Parameters); val.Process(schemaProcessorContext); } } private bool TryHandleSpecialTypes<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(TSchemaType schema, ContextualType contextualType, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { ITypeMapper typeMapper = Settings.TypeMappers.FirstOrDefault((ITypeMapper m) => m.MappedType == contextualType.get_OriginalType()); if (typeMapper == null && contextualType.get_OriginalType().GetTypeInfo().IsGenericType) { Type genericType = contextualType.get_OriginalType().GetGenericTypeDefinition(); typeMapper = Settings.TypeMappers.FirstOrDefault((ITypeMapper m) => m.MappedType == genericType); } if (typeMapper != null) { TypeMapperContext context = new TypeMapperContext(contextualType.get_OriginalType(), this, schemaResolver, AttributeExtensions.GetContextAttributes(contextualType, true)); typeMapper.GenerateSchema(schema, context); return true; } if (!TypeExtensions.IsAssignableToTypeName(contextualType.get_OriginalType(), "JArray", 0) && (TypeExtensions.IsAssignableToTypeName(contextualType.get_OriginalType(), "JToken", 0) || contextualType.get_OriginalType() == typeof(object))) { if (Settings.SchemaType == SchemaType.Swagger2) schema.AllowAdditionalProperties = false; return true; } return false; } private void GenerateEnum<[System.Runtime.CompilerServices.Nullable(0)] TSchemaType>(TSchemaType schema, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver) where TSchemaType : JsonSchema, new { Type type = typeDescription.ContextualType.get_Type(); bool isIntegerEnumeration = (int)typeDescription.Type == 4; if (schemaResolver.HasSchema(type, isIntegerEnumeration)) ((JsonReferenceBase<JsonSchema>)schema).Reference = schemaResolver.GetSchema(type, isIntegerEnumeration); else if (schema.GetType() == typeof(JsonSchema)) { typeDescription.ApplyType(schema); if (Settings.UseXmlDocumentation) schema.Description = XmlDocsExtensions.GetXmlDocsSummary(type, Settings.GetXmlDocsOptions()); GenerateEnum(schema, typeDescription); schemaResolver.AddSchema(type, isIntegerEnumeration, schema); } else { ((JsonReferenceBase<JsonSchema>)schema).Reference = Generate(typeDescription.ContextualType, schemaResolver); } } public bool IsAbstractProperty(ContextualMemberInfo memberInfo) { ContextualPropertyInfo val = memberInfo as ContextualPropertyInfo; if (val != null) { Type declaringType = val.get_PropertyInfo().DeclaringType; if ((object)declaringType != null && !declaringType.GetTypeInfo().IsInterface) { if (!(val.get_PropertyInfo().GetMethod?.IsAbstract ?? false)) return val.get_PropertyInfo().SetMethod?.IsAbstract ?? false; return true; } } return false; } private void GenerateKnownTypes(Type type, JsonSchemaResolver schemaResolver) { object[] customAttributes = type.GetTypeInfo().GetCustomAttributes(Settings.GetActualFlattenInheritanceHierarchy(type)); if (Settings.GenerateKnownTypes) { IEnumerable<Attribute> enumerable = EnumerableExtensions.GetAssignableToTypeName<object>((IEnumerable<object>)customAttributes, "KnownTypeAttribute", 0).OfType<Attribute>(); foreach (dynamic item in enumerable) { if (item.Type != null) this.AddKnownType(item.Type, schemaResolver); else { if (!((item.MethodName != null) ? true : false)) throw new ArgumentException("A KnownType attribute on " + type.FullName + " does not specify a type or a method name.", "type"); MethodInfo runtimeMethod = type.GetRuntimeMethod((string)item.MethodName, Type.EmptyTypes); if (runtimeMethod != (MethodInfo)null) { IEnumerable<Type> enumerable2 = runtimeMethod.Invoke(null, null) as IEnumerable<Type>; if (enumerable2 != null) { foreach (Type item2 in enumerable2) { AddKnownType(item2, schemaResolver); } } } } } } foreach (object item3 in EnumerableExtensions.GetAssignableToTypeName<object>((IEnumerable<object>)customAttributes, "JsonInheritanceAttribute", 0)) { Type type2 = ObjectExtensions.TryGetPropertyValue<Type>(item3, "Type", (Type)null); if (type2 != (Type)null) AddKnownType(type2, schemaResolver); } foreach (object item4 in EnumerableExtensions.GetAssignableToTypeName<object>((IEnumerable<object>)customAttributes, "System.Text.Json.Serialization.JsonDerivedTypeAttribute", 1)) { Type type3 = ObjectExtensions.TryGetPropertyValue<Type>(item4, "DerivedType", (Type)null); if (type3 != (Type)null) AddKnownType(type3, schemaResolver); } } private void AddKnownType(Type type, JsonSchemaResolver schemaResolver) { JsonTypeDescription description = Settings.ReflectionService.GetDescription(ContextualTypeExtensions.ToContextualType(type), Settings); bool isIntegerEnumeration = (int)description.Type == 4; if (!schemaResolver.HasSchema(type, isIntegerEnumeration)) Generate(type, schemaResolver); } [return: System.Runtime.CompilerServices.Nullable(2)] private JsonSchema GenerateInheritance(ContextualType type, JsonSchema schema, JsonSchemaResolver schemaResolver) { ContextualType val = type.get_BaseType(); if (val != null && val.get_Type() != typeof(object) && val.get_Type() != typeof(ValueType) && EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetContextOrTypeAttributes(val, false), "JsonSchemaIgnoreAttribute", 0) == null && EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetContextOrTypeAttributes(val, false), "SwaggerIgnoreAttribute", 0) == null) { string[] excludedTypeNames = Settings.ExcludedTypeNames; if (excludedTypeNames == null || !excludedTypeNames.Contains(val.get_Type().FullName)) { if (!Settings.GetActualFlattenInheritanceHierarchy(CachedType.op_Implicit(type))) { JsonSchema jsonSchema = new JsonSchema(); Settings.ReflectionService.GenerateProperties(jsonSchema, type, Settings, this, schemaResolver); ApplyAdditionalProperties(jsonSchema, CachedType.op_Implicit(type), schemaResolver); JsonTypeDescription description = Settings.ReflectionService.GetDescription(val, Settings); bool flag = description.RequiresSchemaReference(Settings.TypeMappers); if (jsonSchema.Properties.Any() | flag) { JsonSchema jsonSchema2 = Generate(val, schemaResolver); if (flag) { if (schemaResolver.RootObject != jsonSchema2.ActualSchema) schemaResolver.AppendSchema(jsonSchema2.ActualSchema, Settings.SchemaNameGenerator.Generate(CachedType.op_Implicit(val))); schema._allOf.Add(new JsonSchema { Reference = jsonSchema2.ActualSchema }); } else schema._allOf.Add(jsonSchema2); schema._allOf.Add(jsonSchema); return jsonSchema; } Generate(schema, val, schemaResolver); return schema; } JsonTypeDescription description2 = Settings.ReflectionService.GetDescription(val, Settings); if (!description2.IsDictionary && !type.get_Type().IsArray) { Settings.ReflectionService.GenerateProperties(schema, val, Settings, this, schemaResolver); JsonSchema jsonSchema3 = GenerateInheritance(val, schema, schemaResolver); GenerateInheritanceDiscriminator(CachedType.op_Implicit(val), schema, jsonSchema3 ?? schema); } } } if (Settings.GetActualFlattenInheritanceHierarchy(CachedType.op_Implicit(type)) && Settings.GenerateAbstractProperties) { foreach (Type implementedInterface in type.get_Type().GetTypeInfo().ImplementedInterfaces) { ContextualType val2 = ContextualTypeExtensions.ToContextualType(implementedInterface); JsonTypeDescription description3 = Settings.ReflectionService.GetDescription(val2, Settings); if (!description3.IsDictionary && !type.get_Type().IsArray && !typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(implementedInterface.GetTypeInfo())) { Settings.ReflectionService.GenerateProperties(schema, val2, Settings, this, schemaResolver); JsonSchema jsonSchema4 = GenerateInheritance(val2, schema, schemaResolver); GenerateInheritanceDiscriminator(implementedInterface, schema, jsonSchema4 ?? schema); } } } return null; } private void GenerateInheritanceDiscriminator(Type type, JsonSchema schema, JsonSchema typeSchema) { if (!Settings.GetActualFlattenInheritanceHierarchy(type)) { object obj = TryGetInheritanceDiscriminatorConverter(type); if (obj != null) { string text = TryGetInheritanceDiscriminatorName(obj); if (text != null) { if (typeSchema.Properties.TryGetValue(text, out JsonSchemaProperty value)) { if (!value.ActualTypeSchema.Type.IsInteger() && !value.ActualTypeSchema.Type.IsString()) throw new InvalidOperationException("The JSON discriminator property '" + text + "' must be a string|int property on type '" + type.FullName + "' (it is recommended to not implement the discriminator property at all)."); value.IsRequired = true; } OpenApiDiscriminator openApiDiscriminator2 = typeSchema.DiscriminatorObject = new OpenApiDiscriminator { JsonInheritanceConverter = obj, PropertyName = text }; if (!typeSchema.Properties.ContainsKey(text)) typeSchema.Properties[text] = new JsonSchemaProperty { Type = 64, IsRequired = true }; } } else (schema.ResponsibleDiscriminatorObject ?? schema.ActualTypeSchema.ResponsibleDiscriminatorObject)?.AddMapping(type, schema); } } [return: System.Runtime.CompilerServices.Nullable(2)] private object TryGetInheritanceDiscriminatorConverter(Type type) { IEnumerable<Attribute> enumerable = type.GetTypeInfo().GetCustomAttributes(false).OfType<Attribute>(); dynamic val = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(enumerable, "JsonConverterAttribute", 0); if (val != null) { Type type2 = (Type)val.ConverterType; if (type2 != (Type)null && (TypeExtensions.IsAssignableToTypeName(type2, "JsonInheritanceConverter", 0) || TypeExtensions.IsAssignableToTypeName(type2, "JsonInheritanceConverter`1", 0))) { dynamic val2 = ObjectExtensions.HasProperty(val, "ConverterParameters"); dynamic val3 = (val2 ? false : true) ? val2 : (val2 & (val.ConverterParameters != null)); if (!(((val3 ? false : true) ? val3 : (val3 & (val.ConverterParameters.Length > 0))) ? true : false)) return Activator.CreateInstance(val.ConverterType); return Activator.CreateInstance(val.ConverterType, val.ConverterParameters); } } object[] array = (from a in enumerable where TypeExtensions.IsAssignableToTypeName(a.GetType(), "System.Text.Json.Serialization.JsonDerivedTypeAttribute", 1) select a).ToArray(); object[] array2 = array; if (array2.Length != 0) { object obj = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(enumerable, "System.Text.Json.Serialization.JsonPolymorphicAttribute", 1); return new SystemTextJsonInheritanceWrapper(((dynamic)obj)?.TypeDiscriminatorPropertyName ?? "$type", array2); } return null; } [return: System.Runtime.CompilerServices.Nullable(2)] private static string TryGetInheritanceDiscriminatorName(object jsonInheritanceConverter) { return ObjectExtensions.TryGetPropertyValue<string>(jsonInheritanceConverter, "DiscriminatorName", JsonInheritanceConverterAttribute.DefaultDiscriminatorName); } public void AddProperty(JsonSchema parentSchema, ContextualAccessorInfo property, JsonTypeDescription propertyTypeDescription, string propertyName, [System.Runtime.CompilerServices.Nullable(2)] Attribute requiredAttribute, bool hasRequiredAttribute, bool isNullable, [System.Runtime.CompilerServices.Nullable(2)] object defaultValue, JsonSchemaResolver schemaResolver) { Action<JsonSchemaProperty, JsonSchema> transformation = delegate(JsonSchemaProperty propertySchema, JsonSchema typeSchema) { if (Settings.GenerateXmlObjects) propertySchema.GenerateXmlObjectForProperty(property.get_AccessorType(), propertyName); if (hasRequiredAttribute && !propertyTypeDescription.IsEnum && (int)propertyTypeDescription.Type == 64 && !ObjectExtensions.TryGetPropertyValue<bool>((object)requiredAttribute, "AllowEmptyStrings", false)) propertySchema.MinLength = 1; if (!isNullable && Settings.SchemaType == SchemaType.Swagger2 && !parentSchema.RequiredProperties.Contains(propertyName)) parentSchema.RequiredProperties.Add(propertyName); object obj = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetAttributes(property, true), "System.ComponentModel.ReadOnlyAttribute", 1); if ((dynamic)obj != null) propertySchema.IsReadOnly = ((byte)((dynamic)obj).IsReadOnly != 0); if (propertySchema.Description == null) { string text = propertySchema.Description = property.GetDescription(Settings); } if (propertySchema.Example == null) { object obj3 = propertySchema.Example = GenerateExample(property); } object obj4 = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetAttributes(property, true), "System.ObsoleteAttribute", 1); if ((dynamic)obj4 != null) { propertySchema.IsDeprecated = true; propertySchema.DeprecatedMessage = (string)((dynamic)obj4).Message; } propertySchema.Default = ConvertDefaultValue(property.get_AccessorType(), defaultValue); ApplyDataAnnotations(propertySchema, propertyTypeDescription); ApplyPropertyExtensionDataAttributes(propertySchema, property); }; JsonSchemaProperty value = GenerateWithReferenceAndNullability(property.get_AccessorType(), isNullable, schemaResolver, transformation); parentSchema.Properties.Add(propertyName, value); } public virtual bool IsPropertyIgnored(ContextualAccessorInfo accessorInfo, Type parentType) { if (AttributeExtensions.IsAttributeDefined<JsonIgnoreAttribute>(accessorInfo, true)) return true; bool flag = !AttributeExtensions.IsAttributeDefined<JsonPropertyAttribute>(accessorInfo, true) && HasDataContractAttribute(parentType); if ((!flag) ? ((object)flag) : (flag & (GetDataMemberAttribute(accessorInfo, parentType) == null))) return true; return IsPropertyIgnoredBySettings(accessorInfo); } public bool IsPropertyIgnoredBySettings(ContextualAccessorInfo accessorInfo) { if (Settings.IgnoreObsoleteProperties && AttributeExtensions.IsAttributeDefined<ObsoleteAttribute>(accessorInfo, true)) return true; if (AttributeExtensions.IsAttributeDefined<JsonSchemaIgnoreAttribute>(accessorInfo, true)) return true; return false; } [return: System.Runtime.CompilerServices.Nullable(2)] public dynamic GetDataMemberAttribute(ContextualAccessorInfo accessorInfo, Type parentType) { if (!HasDataContractAttribute(parentType)) return null; return EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetAttributes(accessorInfo, true), "DataMemberAttribute", 0); } private static bool HasDataContractAttribute(Type parentType) { return EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(AttributeExtensions.GetAttributes(ContextualTypeExtensions.ToCachedType(parentType), true), "DataContractAttribute", 0) != null; } private static void ApplyRangeAttribute(JsonSchema schema, IEnumerable<Attribute> parentAttributes) { dynamic val = EnumerableExtensions.FirstAssignableToTypeNameOrDefault<Attribute>(parentAttributes, "System.ComponentModel.DataAnnotations.RangeAttribute", 1); if (val != null) { if (val.Minimum != null) { if (val.OperandType == typeof(double)) { double num = (double)Convert.ChangeType(val.Minimum, typeof(double)); if (num > -1.7976931348623157E+308) schema.Minimum = (decimal)num; } else { decimal num2 = (decimal)Convert.ChangeType(val.Minimum, typeof(decimal)); if (num2 > decimal.MinValue) schema.Minimum = num2; } } if (val.Maximum != null) { if (val.OperandType == typeof(double)) { double num3 = (double)Convert.ChangeType(val.Maximum, typeof(double)); if (num3 < 1.7976931348623157E+308) schema.Maximum = (decimal)num3; } else { decimal num4 = (decimal)Convert.ChangeType(val.Maximum, typeof(decimal)); if (num4 < decimal.MaxValue) schema.Maximum = num4; } } } } private static void ApplyTypeExtensionDataAttributes(JsonSchema schema, ContextualType contextualType) { IJsonSchemaExtensionDataAttribute[] extensionAttributes = AttributeExtensions.GetAttributes<IJsonSchemaExtensionDataAttribute>(contextualType, true).ToArray(); ApplyTypeExtensionDataAttributes(schema, extensionAttributes); } private static void ApplyPropertyExtensionDataAttributes(JsonSchemaProperty propertySchema, ContextualAccessorInfo accessorInfo) { IJsonSchemaExtensionDataAttribute[] extensionAttributes = AttributeExtensions.GetAttributes<IJsonSchemaExtensionDataAttribute>(accessorInfo, true).ToArray(); ApplyTypeExtensionDataAttributes(propertySchema, extensionAttributes); } private static void ApplyTypeExtensionDataAttributes(JsonSchema schema, IJsonSchemaExtensionDataAttribute[] extensionAttributes) { if (extensionAttributes.Length != 0) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); foreach (KeyValuePair<string, object> item in extensionAttributes.SelectMany((IJsonSchemaExtensionDataAttribute attribute) => attribute.get_ExtensionData())) { dictionary[item.Key] = item.Value; } schema.ExtensionData = dictionary; } } } }