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;
}
}
}
}