Пример #1
0
        public TSchemaType Generate <TSchemaType>(Type type)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = new TSchemaType();

            var typeDescription = JsonObjectTypeDescription.FromType(type);

            schema.Type   = typeDescription.Type;
            schema.Format = typeDescription.Format;

            if (schema.Type.HasFlag(JsonObjectType.Object))
            {
                schema.Title = type.Name;
                foreach (var property in type.GetRuntimeProperties())
                {
                    LoadProperty(property, schema);
                }
            }
            else if (schema.Type.HasFlag(JsonObjectType.Array))
            {
                schema.Type = JsonObjectType.Array;
                var itemType = type.GenericTypeArguments.Length == 0 ? type.GetElementType() : type.GenericTypeArguments[0];
                schema.Item = Generate <JsonSchema4>(itemType);
            }

            TryLoadEnumerations(type, schema);
            return(schema);
        }
Пример #2
0
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <typeparam name="TSchemaType">The type of the schema type.</typeparam>
        /// <param name="type">The type.</param>
        /// <param name="schemaResolver">The schema resolver.</param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        /// <exception cref="InvalidOperationException">Could not find item type of enumeration type.</exception>
        public TSchemaType Generate <TSchemaType>(Type type, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = new TSchemaType();

            var typeDescription = JsonObjectTypeDescription.FromType(type);

            schema.Type   = typeDescription.Type;
            schema.Format = typeDescription.Format;

            if (schema.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    GenerateDictionary(type, schema, schemaResolver);
                }
                else
                {
                    if (type == typeof(object))
                    {
                        return(new TSchemaType
                        {
                            Type = JsonObjectType.Object,
                            AllowAdditionalProperties = false
                        });
                    }

                    schema.TypeName = GetTypeName(type);

                    if (schemaResolver.HasSchema(type))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type);
                        return(schema);
                    }

                    GenerateObject(type, schema, schemaResolver);
                    GenerateInheritance(type, schema, schemaResolver);
                }
            }
            else if (schema.Type.HasFlag(JsonObjectType.Array))
            {
                schema.Type = JsonObjectType.Array;

                var itemType = type.GenericTypeArguments.Length == 0 ? type.GetElementType() : type.GenericTypeArguments[0];
                if (itemType == null)
                {
                    throw new InvalidOperationException("Could not find item type of enumeration type '" + type.FullName + "'.");
                }

                schema.Item = Generate <JsonSchema4>(itemType, schemaResolver);
            }

            TryLoadEnumerations(type, schema);

            return(schema);
        }
Пример #3
0
        private void LoadProperty <TSchemaType>(PropertyInfo property, TSchemaType parentSchema, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var propertyType            = property.PropertyType;
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType);

            var attributes = property.GetCustomAttributes().ToArray();

            var jsonProperty = Generate <JsonProperty>(propertyType, schemaResolver);

            var propertyName          = property.Name;
            var jsonPropertyAttribute = attributes.FirstOrDefault(a => a is JsonPropertyAttribute) as JsonPropertyAttribute;

            if (jsonPropertyAttribute != null && !string.IsNullOrEmpty(jsonPropertyAttribute.PropertyName))
            {
                propertyName = jsonPropertyAttribute.PropertyName;
            }

            parentSchema.Properties.Add(propertyName, jsonProperty);

            var requiredAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RequiredAttribute");

            if (propertyTypeDescription.IsAlwaysRequired || requiredAttribute != null)
            {
                parentSchema.RequiredProperties.Add(property.Name);
            }

            dynamic descriptionAttribute = TryGetAttribute(attributes, "System.ComponentModel.DescriptionAttribute");

            if (descriptionAttribute != null)
            {
                jsonProperty.Description = descriptionAttribute.Description;
            }

            dynamic regexAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RegularExpressionAttribute");

            if (regexAttribute != null)
            {
                jsonProperty.Pattern = regexAttribute.Pattern;
            }

            dynamic rangeAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RangeAttribute");

            if (rangeAttribute != null)
            {
                if (rangeAttribute.Minimum != null)
                {
                    jsonProperty.Minimum = rangeAttribute.Minimum;
                }
                if (rangeAttribute.Maximum != null)
                {
                    jsonProperty.Maximum = rangeAttribute.Maximum;
                }
            }
        }
        private void LoadProperty <TSchemaType>(PropertyInfo property, TSchemaType parentSchema, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var propertyType            = property.PropertyType;
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType);

            var attributes = property.GetCustomAttributes().ToArray();

            var jsonProperty = Generate <JsonProperty>(propertyType, schemaResolver);
            var propertyName = JsonPathUtilities.GetPropertyName(property);

            parentSchema.Properties.Add(propertyName, jsonProperty);

            var requiredAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RequiredAttribute");

            if (propertyTypeDescription.IsAlwaysRequired || requiredAttribute != null)
            {
                parentSchema.RequiredProperties.Add(property.Name);
            }

            jsonProperty.Description = GetDescription(property, attributes);

            dynamic regexAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RegularExpressionAttribute");

            if (regexAttribute != null)
            {
                jsonProperty.Pattern = regexAttribute.Pattern;
            }

            dynamic rangeAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RangeAttribute");

            if (rangeAttribute != null)
            {
                if (rangeAttribute.Minimum != null)
                {
                    jsonProperty.Minimum = rangeAttribute.Minimum;
                }
                if (rangeAttribute.Maximum != null)
                {
                    jsonProperty.Maximum = rangeAttribute.Maximum;
                }
            }
        }
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <typeparam name="TSchemaType">The type of the schema type.</typeparam>
        /// <param name="type">The type.</param>
        /// <param name="parentAttributes">The parent property or parameter attributes.</param>
        /// <param name="schemaResolver">The schema resolver.</param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        /// <exception cref="InvalidOperationException">Could not find item type of array type.</exception>
        public TSchemaType Generate <TSchemaType>(Type type, IEnumerable <Attribute> parentAttributes, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = HandleSpecialTypes <TSchemaType>(type);

            if (schema != null)
            {
                return(schema);
            }

            schema = new TSchemaType();

            var typeDescription = JsonObjectTypeDescription.FromType(type);

            schema.Type   = typeDescription.Type;
            schema.Format = typeDescription.Format;

            if (schema.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    GenerateDictionary(type, schema, schemaResolver);
                }
                else
                {
                    schema.TypeName = GetTypeName(type);

                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                        return(schema);
                    }

                    schema.Description = GetDescription(type.GetTypeInfo(), type.GetTypeInfo().GetCustomAttributes());

                    GenerateObject(type, schema, schemaResolver);
                }
            }
            else if (schema.Type.HasFlag(JsonObjectType.Array))
            {
                schema.Type = JsonObjectType.Array;

                var genericTypeArguments = GetGenericTypeArguments(type);
                var itemType             = genericTypeArguments.Length == 0 ? type.GetElementType() : genericTypeArguments[0];
                if (itemType == null)
                {
                    throw new InvalidOperationException("Could not find item type of array type '" + type.FullName + "'.");
                }

                schema.Item = Generate <JsonSchema4>(itemType, schemaResolver);
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = IsIntegerEnumeration(parentAttributes) || HasStringEnumConverter(type.GetTypeInfo().GetCustomAttributes());

                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.Type            = isIntegerEnumeration ? JsonObjectType.Integer : JsonObjectType.String;
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                    return(schema);
                }

                LoadEnumerations(type, schema, isIntegerEnumeration, parentAttributes);

                schema.TypeName = GetTypeName(type);
                schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
            }

            return(schema);
        }
        private void LoadProperty <TSchemaType>(PropertyInfo property, TSchemaType parentSchema, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var propertyType            = property.PropertyType;
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType);

            var attributes = property.GetCustomAttributes().ToArray();

            if (attributes.All(a => !(a is JsonIgnoreAttribute)))
            {
                var jsonProperty = Generate <JsonProperty>(propertyType, property.GetCustomAttributes(), schemaResolver);
                var propertyName = JsonPathUtilities.GetPropertyName(property);
                parentSchema.Properties.Add(propertyName, jsonProperty);

                var jsonPropertyAttribute  = property.GetCustomAttribute <JsonPropertyAttribute>();
                var isJsonPropertyRequired = jsonPropertyAttribute != null && jsonPropertyAttribute.Required == Required.Always;

                var requiredAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RequiredAttribute");
                if (propertyTypeDescription.IsAlwaysRequired || requiredAttribute != null || isJsonPropertyRequired)
                {
                    parentSchema.RequiredProperties.Add(propertyName);
                }

                dynamic displayAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.DisplayAttribute");
                if (displayAttribute != null && displayAttribute.Name != null)
                {
                    jsonProperty.Title = displayAttribute.Name;
                }

                jsonProperty.Description = GetDescription(property, attributes);

                dynamic regexAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RegularExpressionAttribute");
                if (regexAttribute != null)
                {
                    jsonProperty.Pattern = regexAttribute.Pattern;
                }

                if (propertyTypeDescription.Type == JsonObjectType.Number || propertyTypeDescription.Type == JsonObjectType.Integer)
                {
                    dynamic rangeAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RangeAttribute");
                    if (rangeAttribute != null)
                    {
                        if (rangeAttribute.Minimum != null)
                        {
                            jsonProperty.Minimum = rangeAttribute.Minimum;
                        }
                        if (rangeAttribute.Maximum != null)
                        {
                            jsonProperty.Maximum = rangeAttribute.Maximum;
                        }
                    }
                }

                dynamic minLengthAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.MinLengthAttribute");
                if (minLengthAttribute != null && minLengthAttribute.Length != null)
                {
                    if (propertyTypeDescription.Type == JsonObjectType.String)
                    {
                        jsonProperty.MinLength = minLengthAttribute.Length;
                    }
                    else if (propertyTypeDescription.Type == JsonObjectType.Array)
                    {
                        jsonProperty.MinItems = minLengthAttribute.Length;
                    }
                }

                dynamic maxLengthAttribute = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.MaxLengthAttribute");
                if (maxLengthAttribute != null && maxLengthAttribute.Length != null)
                {
                    if (propertyTypeDescription.Type == JsonObjectType.String)
                    {
                        jsonProperty.MaxLength = maxLengthAttribute.Length;
                    }
                    else if (propertyTypeDescription.Type == JsonObjectType.Array)
                    {
                        jsonProperty.MaxItems = maxLengthAttribute.Length;
                    }
                }
            }
        }
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <typeparam name="TSchemaType">The type of the schema type.</typeparam>
        /// <param name="type">The type.</param>
        /// <param name="schemaResolver">The schema resolver.</param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        /// <exception cref="InvalidOperationException">Could not find item type of enumeration type.</exception>
        public TSchemaType Generate <TSchemaType>(Type type, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = new TSchemaType();

            var typeDescription = JsonObjectTypeDescription.FromType(type);

            schema.Type   = typeDescription.Type;
            schema.Format = typeDescription.Format;

            if (schema.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    GenerateDictionary(type, schema, schemaResolver);
                }
                else
                {
                    if (type == typeof(object))
                    {
                        return(new TSchemaType
                        {
                            Type = JsonObjectType.Object,
                            AllowAdditionalProperties = false
                        });
                    }

                    schema.TypeName = GetTypeName(type);

                    if (schemaResolver.HasSchema(type))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type);
                        return(schema);
                    }

                    schema.Description = GetDescription(type.GetTypeInfo(), type.GetTypeInfo().GetCustomAttributes());

                    GenerateObject(type, schema, schemaResolver);
                    GenerateInheritance(type, schema, schemaResolver);
                }
            }
            else if (schema.Type.HasFlag(JsonObjectType.Array))
            {
                schema.Type = JsonObjectType.Array;

                var itemType = type.GenericTypeArguments.Length == 0 ? type.GetElementType() : type.GenericTypeArguments[0];
                if (itemType == null)
                {
                    throw new InvalidOperationException("Could not find item type of enumeration type '" + type.FullName + "'.");
                }

                schema.Item = Generate <JsonSchema4>(itemType, schemaResolver);
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                if (schemaResolver.HasSchema(type))
                {
                    schema.SchemaReference = schemaResolver.GetSchema(type);
                    return(schema);
                }

                dynamic jsonConverterAttribute = type.GetTypeInfo().GetCustomAttributes()
                                                 .SingleOrDefault(a => a.GetType().Name == "JsonConverterAttribute");

                if (jsonConverterAttribute != null)
                {
                    var converterType = (Type)jsonConverterAttribute.ConverterType;
                    if (converterType.Name == "StringEnumConverter")
                    {
                        LoadEnumerations(type, schema);
                    }
                    else if (Settings.DefaultEnumHandling == EnumHandling.String)
                    {
                        LoadEnumerations(type, schema);
                    }
                }
                else if (Settings.DefaultEnumHandling == EnumHandling.String)
                {
                    LoadEnumerations(type, schema);
                }

                schema.TypeName = type.Name;
                schemaResolver.AddSchema(type, schema);
            }

            return(schema);
        }
Пример #8
0
        private void AddPrimitiveParametersFromUri(string name, SwaggerOperation operation, ParameterInfo parameter, JsonObjectTypeDescription typeDescription, SwaggerGenerator swaggerGenerator)
        {
            if (typeDescription.Type.HasFlag(JsonObjectType.Array))
            {
                var operationParameter = swaggerGenerator.CreatePrimitiveParameter(name,
                    parameter.GetXmlDocumentation(), parameter.ParameterType.GetEnumerableItemType(), parameter.GetCustomAttributes().ToList());

                operationParameter.Kind = SwaggerParameterKind.Query;
                operationParameter.CollectionFormat = SwaggerParameterCollectionFormat.Multi;
                operation.Parameters.Add(operationParameter);
            }
            else
            {
                foreach (var property in parameter.ParameterType.GetRuntimeProperties())
                {
                    var attributes = property.GetCustomAttributes().ToList();
                    var fromQueryAttribute = attributes.SingleOrDefault(a => a.GetType().Name == "FromQueryAttribute");

                    var propertyName = TryGetStringPropertyValue(fromQueryAttribute, "Name") ?? JsonPathUtilities.GetPropertyName(property, _settings.DefaultPropertyNameHandling);
                    var operationParameter = swaggerGenerator.CreatePrimitiveParameter(propertyName, property.GetXmlSummary(), property.PropertyType, attributes);

                    // TODO: Check if required can be controlled with mechanisms other than RequiredAttribute

                    var parameterInfo = JsonObjectTypeDescription.FromType(property.PropertyType, attributes, _settings.DefaultEnumHandling);
                    var isFileArray = IsFileArray(property.PropertyType, parameterInfo);
                    if (parameterInfo.Type == JsonObjectType.File || isFileArray)
                        InitializeFileParameter(operationParameter, isFileArray);
                    else
                        operationParameter.Kind = SwaggerParameterKind.Query;

                    operation.Parameters.Add(operationParameter);
                }
            }
        }
Пример #9
0
 private bool IsFileArray(Type type, JsonObjectTypeDescription typeInfo)
 {
     var isFormFileCollection = type.Name == "IFormFileCollection";
     var isFileArray = typeInfo.Type == JsonObjectType.Array && type.GenericTypeArguments.Any() &&
                       JsonObjectTypeDescription.FromType(type.GenericTypeArguments[0], null, _settings.DefaultEnumHandling).Type == JsonObjectType.File;
     return isFormFileCollection || isFileArray;
 }
Пример #10
0
        private bool TryAddFileParameter(JsonObjectTypeDescription info, SwaggerOperation operation, ParameterInfo parameter, SwaggerGenerator swaggerGenerator)
        {
            var isFileArray = IsFileArray(parameter.ParameterType, info);
            if (info.Type == JsonObjectType.File || isFileArray)
            {
                AddFileParameter(parameter, isFileArray, operation, swaggerGenerator);
                return true;
            }

            return false;
        }
Пример #11
0
        /// <exception cref="InvalidOperationException">Could not find item type of array type.</exception>
        private TSchemaType Generate <TSchemaType>(Type type, PropertyInfo propertyInfo, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            if (type == typeof(object) || type == typeof(JObject))
            {
                return(new TSchemaType
                {
                    Type = JsonObjectType.Object,
                    AllowAdditionalProperties = true
                });
            }

            var schema = new TSchemaType();

            var typeDescription = JsonObjectTypeDescription.FromType(type);

            schema.Type   = typeDescription.Type;
            schema.Format = typeDescription.Format;

            if (schema.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    GenerateDictionary(type, schema, schemaResolver);
                }
                else
                {
                    schema.TypeName = GetTypeName(type);

                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                        return(schema);
                    }

                    schema.Description = GetDescription(type.GetTypeInfo(), type.GetTypeInfo().GetCustomAttributes());

                    GenerateObject(type, schema, schemaResolver);
                }
            }
            else if (schema.Type.HasFlag(JsonObjectType.Array))
            {
                schema.Type = JsonObjectType.Array;

                var genericTypeArguments = GetGenericTypeArguments(type);
                var itemType             = genericTypeArguments.Length == 0 ? type.GetElementType() : genericTypeArguments[0];
                if (itemType == null)
                {
                    throw new InvalidOperationException("Could not find item type of array type '" + type.FullName + "'.");
                }

                schema.Item = Generate <JsonSchema4>(itemType, schemaResolver);
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = IsIntegerEnumeration(propertyInfo);

                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.Type            = isIntegerEnumeration ? JsonObjectType.Integer : JsonObjectType.String;
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                    return(schema);
                }

                LoadEnumerations(type, schema, isIntegerEnumeration);

                schema.TypeName = GetTypeName(type);
                schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
            }

            return(schema);
        }