private void LoadDefaultReturnType(SwaggerOperation operation, MethodInfo method, string xmlDescription,
                                           ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var returnType = method.ReturnType;

            if (returnType == typeof(Task))
            {
                returnType = typeof(void);
            }
            else if (returnType.Name == "Task`1")
            {
                returnType = returnType.GenericTypeArguments[0];
            }

            if (IsVoidResponse(returnType))
            {
                operation.Responses["204"] = new SwaggerResponse
                {
                    Description = xmlDescription ?? string.Empty,
                };
            }
            else
            {
                var typeDescription = JsonObjectTypeDescription.FromType(returnType,
                                                                         method.ReturnParameter?.GetCustomAttributes(), Settings.DefaultEnumHandling);
                operation.Responses["200"] = new SwaggerResponse
                {
                    Description   = xmlDescription ?? string.Empty,
                    IsNullableRaw = typeDescription.IsNullable,
                    Schema        = CreateAndAddSchema(returnType, typeDescription.IsNullable, null, schemaResolver, schemaDefinitionAppender)
                };
            }
        }
Example #2
0
 /// <summary>Initializes a new instance of the <see cref="SwaggerGenerator"/> class.</summary>
 /// <param name="schemaGenerator">The schema generator.</param>
 /// <param name="schemaGeneratorSettings">The schema generator settings.</param>
 /// <param name="schemaResolver">The schema resolver.</param>
 /// <param name="schemaDefinitionAppender">The schema definition appender.</param>
 public SwaggerGenerator(JsonSchemaGenerator schemaGenerator, JsonSchemaGeneratorSettings schemaGeneratorSettings, 
     ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
 {
     _schemaGenerator = schemaGenerator;
     _schemaResolver = schemaResolver;
     _schemaDefinitionAppender = schemaDefinitionAppender;
     _settings = schemaGeneratorSettings;
 }
        private void AddPrimitiveParameter(string name, SwaggerOperation operation, ParameterInfo parameter,
                                           ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var operationParameter = CreatePrimitiveParameter(name, parameter, schemaResolver, schemaDefinitionAppender);

            operationParameter.Kind       = SwaggerParameterKind.Query;
            operationParameter.IsRequired = operationParameter.IsRequired || parameter.HasDefaultValue == false;
            operation.Parameters.Add(operationParameter);
        }
        /// <exception cref="InvalidOperationException">The operation has more than one body parameter.</exception>
        private void GenerateForController(SwaggerService service, Type controllerType, string excludedMethodName,
                                           ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var hasIgnoreAttribute = controllerType.GetTypeInfo().GetCustomAttributes()
                                     .Any(a => a.GetType().Name == "SwaggerIgnoreAttribute");

            if (!hasIgnoreAttribute)
            {
                var operations = new List <Tuple <SwaggerOperationDescription, MethodInfo> >();
                foreach (var method in GetActionMethods(controllerType, excludedMethodName))
                {
                    var httpPaths   = GetHttpPaths(controllerType, method);
                    var httpMethods = GetSupportedHttpMethods(method).ToList();

                    foreach (var httpPath in httpPaths)
                    {
                        foreach (var httpMethod in httpMethods)
                        {
                            var operation = new SwaggerOperation
                            {
                                IsDeprecated = method.GetCustomAttribute <ObsoleteAttribute>() != null
                            };

                            var parameters = method.GetParameters().ToList();

                            LoadParameters(operation, parameters, httpPath, schemaResolver, schemaDefinitionAppender);
                            LoadReturnType(operation, method, schemaResolver, schemaDefinitionAppender);
                            LoadMetaData(operation, method);
                            LoadOperationTags(method, operation, controllerType);

                            var operationDescription = new SwaggerOperationDescription
                            {
                                Path = Regex.Replace(httpPath, "{(.*?)(:(.*?))?}", match =>
                                {
                                    if (operation.ActualParameters.Any(p => p.Kind == SwaggerParameterKind.Path && match.Groups[1].Value == p.Name))
                                    {
                                        return("{" + match.Groups[1].Value + "}");
                                    }
                                    return(string.Empty);
                                }).TrimEnd('/'),
                                Method    = httpMethod,
                                Operation = operation
                            };

                            operationDescription.Operation.OperationId = GetOperationId(service, controllerType.Name, method);
                            operations.Add(new Tuple <SwaggerOperationDescription, MethodInfo>(operationDescription, method));
                        }
                    }
                }

                AddOperationDescriptionsToDocument(service, operations, schemaResolver);
            }

            AppendRequiredSchemasToDefinitions(service, schemaResolver);
        }
        private void AddFileParameter(ParameterInfo parameter, bool isFileArray, SwaggerOperation operation,
                                      ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var attributes = parameter.GetCustomAttributes().ToList();

            // TODO: Check if there is a way to control the property name
            var operationParameter = CreatePrimitiveParameter(parameter.Name, parameter.GetXmlDocumentation(),
                                                              parameter.ParameterType, attributes, schemaResolver, schemaDefinitionAppender);

            InitializeFileParameter(operationParameter, isFileArray);
            operation.Parameters.Add(operationParameter);
        }
Example #6
0
        /// <summary>Generates the properties for the given type and schema.</summary>
        /// <typeparam name="TSchemaType">The type of the schema type.</typeparam>
        /// <param name="type">The types.</param>
        /// <param name="schema">The properties</param>
        /// <param name="rootSchema">The root schema.</param>
        /// <param name="schemaDefinitionAppender"></param>
        /// <param name="schemaResolver">The schema resolver.</param>
        protected virtual void GenerateObject <TSchemaType>(Type type, TSchemaType schema, JsonSchema4 rootSchema,
                                                            ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            schemaResolver.AddSchema(type, false, schema);
            schema.AllowAdditionalProperties = false;

            GeneratePropertiesAndInheritance(type, schema, rootSchema, schemaDefinitionAppender, schemaResolver);
            if (Settings.GenerateKnownTypes)
            {
                GenerateKnownTypes(type, rootSchema, schemaDefinitionAppender, schemaResolver);
            }
        }
        private bool TryAddFileParameter(JsonObjectTypeDescription info, SwaggerOperation operation, ParameterInfo parameter,
                                         ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var isFileArray = IsFileArray(parameter.ParameterType, info);

            if (info.Type == JsonObjectType.File || isFileArray)
            {
                AddFileParameter(parameter, isFileArray, operation, schemaResolver, schemaDefinitionAppender);
                return(true);
            }

            return(false);
        }
Example #8
0
        private void GenerateKnownTypes(Type type, JsonSchema4 rootSchema, ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
        {
            foreach (var knownTypeAttribute in type.GetTypeInfo().GetCustomAttributes <KnownTypeAttribute>())
            {
                var typeDescription = JsonObjectTypeDescription.FromType(knownTypeAttribute.Type, null, Settings.DefaultEnumHandling);
                var isIntegerEnum   = typeDescription.Type == JsonObjectType.Integer;

                if (!schemaResolver.HasSchema(knownTypeAttribute.Type, isIntegerEnum))
                {
                    var knownSchema = Generate(knownTypeAttribute.Type, rootSchema, null, schemaDefinitionAppender, schemaResolver);
                    schemaDefinitionAppender.Append(rootSchema, knownSchema.ActualSchema);
                }
            }
        }
Example #9
0
        private void GenerateKnownTypes(Type type, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            foreach (dynamic knownTypeAttribute in type.GetTypeInfo().GetCustomAttributes().Where(a => a.GetType().Name == "KnownTypeAttribute"))
            {
                var typeDescription = JsonObjectTypeDescription.FromType(knownTypeAttribute.Type, null, Settings.DefaultEnumHandling);
                var isIntegerEnum   = typeDescription.Type == JsonObjectType.Integer;

                if (!schemaResolver.HasSchema(knownTypeAttribute.Type, isIntegerEnum))
                {
                    var knownSchema = Generate(knownTypeAttribute.Type, schemaResolver, schemaDefinitionAppender);
                    schemaDefinitionAppender.Append(knownSchema.ActualSchema);
                }
            }
        }
        /// <summary>Gets the JSON path of the given object.</summary>
        /// <param name="root">The root object.</param>
        /// <param name="objectToSearch">The object to search.</param>
        /// <param name="schemaDefinitionAppender">Appends the <paramref name="objectToSearch"/> to the 'definitions' if it could not be found.</param>
        /// <returns>The path or <c>null</c> when the object could not be found.</returns>
        /// <exception cref="InvalidOperationException">Could not find the JSON path of a child object.</exception>
        public static string GetJsonPath(object root, object objectToSearch, ISchemaDefinitionAppender schemaDefinitionAppender = null)
        {
            var path = GetJsonPath(root, objectToSearch, "#", new HashSet<object>());
            if (path == null)
            {
                if (schemaDefinitionAppender != null && objectToSearch is JsonSchema4)
                {
                    schemaDefinitionAppender.Append(root, (JsonSchema4)objectToSearch);
                    return GetJsonPath(root, objectToSearch, schemaDefinitionAppender);
                }
                else
                    throw new InvalidOperationException("Could not find the JSON path of a child object.");

            }
            return path;
        }
Example #11
0
        /// <summary>Gets the JSON path of the given object.</summary>
        /// <param name="root">The root object.</param>
        /// <param name="objectToSearch">The object to search.</param>
        /// <param name="schemaDefinitionAppender">Appends the <paramref name="objectToSearch"/> to the 'definitions' if it could not be found.</param>
        /// <returns>The path or <c>null</c> when the object could not be found.</returns>
        /// <exception cref="InvalidOperationException">Could not find the JSON path of a child object.</exception>
        public static string GetJsonPath(object root, object objectToSearch, ISchemaDefinitionAppender schemaDefinitionAppender = null)
        {
            var path = GetJsonPath(root, objectToSearch, "#", new List <object>());

            if (path == null)
            {
                if (schemaDefinitionAppender != null && objectToSearch is JsonSchema4)
                {
                    schemaDefinitionAppender.Append(root, (JsonSchema4)objectToSearch);
                    return(GetJsonPath(root, objectToSearch, schemaDefinitionAppender));
                }
                else
                {
                    throw new InvalidOperationException("Could not find the JSON path of a child object.");
                }
            }
            return(path);
        }
Example #12
0
        /// <summary>Gets the JSON path of the given object.</summary>
        /// <param name="root">The root object.</param>
        /// <param name="searchedObject">The object to search.</param>
        /// <param name="schemaDefinitionAppender">Appends the <paramref name="searchedObject"/> to the 'definitions' if it could not be found.</param>
        /// <returns>The path or <c>null</c> when the object could not be found.</returns>
        /// <exception cref="InvalidOperationException">Could not find the JSON path of a child object.</exception>
        public static string GetJsonPath(object root, object searchedObject, ISchemaDefinitionAppender schemaDefinitionAppender = null)
        {
            var path = GetJsonPath(root, searchedObject, "#", new HashSet <object>());

            if (path == null)
            {
                var searchedSchema = searchedObject as JsonSchema4;
                if (schemaDefinitionAppender != null && searchedSchema != null)
                {
                    schemaDefinitionAppender.Append(searchedSchema);
                    return(GetJsonPath(root, searchedObject, schemaDefinitionAppender));
                }
                else
                {
                    throw new InvalidOperationException("Could not find the JSON path of a child object.");
                }
            }
            return(path);
        }
 private SwaggerParameter CreatePrimitiveParameter(string name, ParameterInfo parameter,
                                                   ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
 {
     return(CreatePrimitiveParameter(name, parameter.GetXmlDocumentation(), parameter.ParameterType, parameter.GetCustomAttributes().ToList(),
                                     schemaResolver, schemaDefinitionAppender));
 }
Example #14
0
        private void GenerateInheritance(Type type, JsonSchema4 schema, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            GenerateInheritanceDiscriminator(type, schema);

            var baseType = type.GetTypeInfo().BaseType;

            if (baseType != null && baseType != typeof(object))
            {
                if (Settings.FlattenInheritanceHierarchy)
                {
                    GeneratePropertiesAndInheritance(baseType, schema, schemaResolver, schemaDefinitionAppender);
                }
                else
                {
                    var baseSchema = Generate(baseType, schemaResolver, schemaDefinitionAppender);
                    schema.AllOf.Add(baseSchema);
                }
            }
        }
Example #15
0
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        private void GenerateDictionary <TSchemaType>(Type type, TSchemaType schema, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
            where TSchemaType : JsonSchema4, new()
        {
            var genericTypeArguments = ReflectionExtensions.GetGenericTypeArguments(type);

            var valueType = genericTypeArguments.Length == 2 ? genericTypeArguments[1] : typeof(object);

            if (valueType == typeof(object))
            {
                schema.AdditionalPropertiesSchema = JsonSchema4.CreateAnySchema();
            }
            else
            {
                if (RequiresSchemaReference(valueType, null))
                {
                    schema.AdditionalPropertiesSchema = new JsonSchema4
                    {
                        SchemaReference = Generate(valueType, schemaResolver, schemaDefinitionAppender)
                    };
                }
                else
                {
                    schema.AdditionalPropertiesSchema = Generate(valueType, schemaResolver, schemaDefinitionAppender);
                }
            }

            schema.AllowAdditionalProperties = true;
        }
Example #16
0
        private void GeneratePropertiesAndInheritance(Type type, JsonSchema4 schema, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var properties = GetTypeProperties(type);

#if !LEGACY
            var declaredFields = type.GetTypeInfo().DeclaredFields
                                 .Where(f => f.IsPublic);

            var declaredProperties = type.GetTypeInfo().DeclaredProperties
                                     .Where(p => p.GetMethod?.IsPublic == true || p.SetMethod?.IsPublic == true);
#else
            var declaredFields = type.GetTypeInfo()
                                 .GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);

            var declaredProperties = type.GetTypeInfo()
                                     .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
                                     .Where(p => p.GetGetMethod()?.IsPublic == true || p.GetSetMethod()?.IsPublic == true);
#endif

            foreach (var property in declaredProperties.Where(p => properties == null || properties.Contains(p.Name)))
            {
                LoadPropertyOrField(property, property.PropertyType, type, schema, schemaResolver, schemaDefinitionAppender);
            }

            foreach (var field in declaredFields.Where(p => properties == null || properties.Contains(p.Name)))
            {
                LoadPropertyOrField(field, field.FieldType, type, schema, schemaResolver, schemaDefinitionAppender);
            }

            GenerateInheritance(type, schema, schemaResolver, schemaDefinitionAppender);
        }
 /// <summary>Updates the <see cref="JsonSchema4.SchemaReferencePath" /> properties
 /// from the available <see cref="JsonSchema4.SchemaReference" /> properties.</summary>
 /// <param name="root">The root.</param>
 /// <param name="schemaDefinitionAppender">The schema definition appender.</param>
 public static void UpdateSchemaReferencePaths(object root, ISchemaDefinitionAppender schemaDefinitionAppender)
 {
     UpdateSchemaReferencePaths(root, root, new HashSet <object>(), schemaDefinitionAppender);
 }
Example #18
0
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <param name="type">The type.</param>
        /// <param name="rootSchema">The root schema.</param>
        /// <param name="parentAttributes">The parent property or parameter attributes.</param>
        /// <param name="schemaDefinitionAppender">The schema definition appender.</param>
        /// <param name="schemaResolver">The schema resolver.</param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        public TSchemaType Generate <TSchemaType>(Type type, JsonSchema4 rootSchema, IEnumerable <Attribute> parentAttributes, ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = HandleSpecialTypes <TSchemaType>(type);

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

            schema = new TSchemaType();

            if (rootSchema == null)
            {
                rootSchema = schema;
            }

            var typeDescription = JsonObjectTypeDescription.FromType(type, parentAttributes, Settings.DefaultEnumHandling);

            typeDescription.ApplyType(schema);

            ApplyExtensionDataAttributes(schema, type, parentAttributes);

            if (schema.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    GenerateDictionary(type, rootSchema, schema, schemaDefinitionAppender, schemaResolver);
                }
                else
                {
                    schema.TypeNameRaw = GetTypeName(type);
                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                        return(schema);
                    }

                    if (schema.GetType() == typeof(JsonSchema4))
                    {
                        schema.Description = GetDescription(type.GetTypeInfo(), type.GetTypeInfo().GetCustomAttributes());
                        GenerateObject(type, schema, rootSchema, schemaDefinitionAppender, schemaResolver);
                    }
                    else
                    {
                        schema.SchemaReference = Generate(type, rootSchema, parentAttributes, schemaDefinitionAppender, schemaResolver);
                        return(schema);
                    }
                }
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = typeDescription.Type == JsonObjectType.Integer;
                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.Type            = typeDescription.Type;
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                    return(schema);
                }

                if (schema.GetType() == typeof(JsonSchema4))
                {
                    LoadEnumerations(type, schema, typeDescription);

                    schema.TypeNameRaw = GetTypeName(type);
                    schema.Description = type.GetXmlDocumentation();
                    schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
                }
                else
                {
                    schema.SchemaReference = Generate(type, rootSchema, parentAttributes, schemaDefinitionAppender, schemaResolver);
                    return(schema);
                }
            }
            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)
                {
                    schema.Item = JsonSchema4.CreateAnySchema();
                }
                else
                {
                    schema.Item = Generate(itemType, rootSchema, null, schemaDefinitionAppender, schemaResolver);
                }
            }

            return(schema);
        }
        private SwaggerParameter CreatePrimitiveParameter(string name, string description, Type type, IList <Attribute> parentAttributes,
                                                          ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var typeDescription = JsonObjectTypeDescription.FromType(type, parentAttributes, Settings.DefaultEnumHandling);
            var parameterType   = typeDescription.Type.HasFlag(JsonObjectType.Object) ? typeof(string) : type; // object types must be treated as string

            var operationParameter = _schemaGenerator.Generate <SwaggerParameter>(parameterType, parentAttributes, schemaResolver, schemaDefinitionAppender);

            if (parameterType.GetTypeInfo().IsEnum)
            {
                operationParameter.SchemaReference = _schemaGenerator.Generate <JsonSchema4>(parameterType, parentAttributes, schemaResolver, schemaDefinitionAppender);
            }
            else
            {
                _schemaGenerator.ApplyPropertyAnnotations(operationParameter, type, parentAttributes, typeDescription);
            }

            operationParameter.Name          = name;
            operationParameter.IsRequired    = parentAttributes?.Any(a => a.GetType().Name == "RequiredAttribute") ?? false;
            operationParameter.IsNullableRaw = typeDescription.IsNullable;

            if (description != string.Empty)
            {
                operationParameter.Description = description;
            }

            return(operationParameter);
        }
Example #20
0
        /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
        /// <param name="type">The type.</param>
        /// <param name="parentAttributes">The parent property or parameter attributes.</param>
        /// <param name="schemaResolver"></param>
        /// <param name="schemaDefinitionAppender"></param>
        /// <returns>The schema.</returns>
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        public virtual TSchemaType Generate <TSchemaType>(Type type, IEnumerable <Attribute> parentAttributes,
                                                          ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
            where TSchemaType : JsonSchema4, new()
        {
            var schema = HandleSpecialTypes <TSchemaType>(type, schemaResolver);

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

            schema = new TSchemaType();

            if (schemaDefinitionAppender.RootObject == null)
            {
                schemaDefinitionAppender.RootObject = schema;
            }

            ApplyExtensionDataAttributes(schema, type, parentAttributes);

            var typeDescription = JsonObjectTypeDescription.FromType(type, parentAttributes, Settings.DefaultEnumHandling);

            if (typeDescription.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    typeDescription.ApplyType(schema);
                    GenerateDictionary(type, schema, schemaResolver, schemaDefinitionAppender);
                }
                else
                {
                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                        return(schema);
                    }

                    if (schema.GetType() == typeof(JsonSchema4))
                    {
                        typeDescription.ApplyType(schema);

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

                        GenerateObject(type, schema, schemaResolver, schemaDefinitionAppender);
                    }
                    else
                    {
                        schema.SchemaReference = Generate <JsonSchema4>(type, parentAttributes, schemaResolver, schemaDefinitionAppender);
                        return(schema);
                    }
                }
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = typeDescription.Type == JsonObjectType.Integer;
                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                    return(schema);
                }

                if (schema.GetType() == typeof(JsonSchema4))
                {
                    LoadEnumerations(type, schema, typeDescription);

                    typeDescription.ApplyType(schema);

                    schema.TypeNameRaw = ReflectionExtensions.GetSafeTypeName(type);
                    schema.Description = type.GetXmlSummary();

                    schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
                }
                else
                {
                    schema.SchemaReference = Generate <JsonSchema4>(type, parentAttributes, schemaResolver, schemaDefinitionAppender);
                    return(schema);
                }
            }
            else if (typeDescription.Type.HasFlag(JsonObjectType.Array))
            {
                typeDescription.ApplyType(schema);

                var itemType = type.GetEnumerableItemType();
                if (itemType == null)
                {
                    var jsonSchemaAttribute = type.GetTypeInfo().GetCustomAttribute <JsonSchemaAttribute>();
                    if (jsonSchemaAttribute?.ArrayItem != null)
                    {
                        schema.Item = Generate(jsonSchemaAttribute.ArrayItem, schemaResolver, schemaDefinitionAppender);
                    }
                    else
                    {
                        schema.Item = JsonSchema4.CreateAnySchema();
                    }
                }
                else
                {
                    if (itemType.GetTypeInfo().IsEnum)
                    {
                        schema.Item = new JsonSchema4 {
                            SchemaReference = Generate(itemType, schemaResolver, schemaDefinitionAppender)
                        }
                    }
                    ;
                    else
                    {
                        schema.Item = Generate(itemType, schemaResolver, schemaDefinitionAppender);
                    }
                }
            }
            else
            {
                typeDescription.ApplyType(schema);
            }

            return(schema);
        }
        private void LoadReturnType(SwaggerOperation operation, MethodInfo method,
                                    ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var xmlDescription = method.ReturnParameter.GetXmlDocumentation();

            if (xmlDescription == string.Empty)
            {
                xmlDescription = null;
            }

            var responseTypeAttributes = method.GetCustomAttributes()
                                         .Where(a => a.GetType().Name == "ResponseTypeAttribute")
                                         .ToList();

            var producesResponseTypeAttributes = method.GetCustomAttributes()
                                                 .Where(a => a.GetType().Name == "ProducesResponseTypeAttribute")
                                                 .ToList();

            if (responseTypeAttributes.Any() || producesResponseTypeAttributes.Any())
            {
                foreach (var responseTypeAttribute in responseTypeAttributes)
                {
                    dynamic dynResultTypeAttribute = responseTypeAttribute;
                    var     returnType             = dynResultTypeAttribute.ResponseType;

                    var httpStatusCode = IsVoidResponse(returnType) ? "204" : "200";
                    if (responseTypeAttribute.GetType().GetRuntimeProperty("HttpStatusCode") != null)
                    {
                        httpStatusCode = dynResultTypeAttribute.HttpStatusCode;
                    }

                    var description = xmlDescription;
                    if (responseTypeAttribute.GetType().GetRuntimeProperty("Description") != null)
                    {
                        if (!string.IsNullOrEmpty(dynResultTypeAttribute.Description))
                        {
                            description = dynResultTypeAttribute.Description;
                        }
                    }

                    var typeDescription = JsonObjectTypeDescription.FromType(returnType, method.ReturnParameter?.GetCustomAttributes(), Settings.DefaultEnumHandling);
                    var response        = new SwaggerResponse
                    {
                        Description   = description ?? string.Empty,
                        IsNullableRaw = typeDescription.IsNullable
                    };

                    if (IsVoidResponse(returnType) == false)
                    {
                        response.Schema = CreateAndAddSchema(returnType, typeDescription.IsNullable, null,
                                                             schemaResolver, schemaDefinitionAppender);
                    }

                    operation.Responses[httpStatusCode] = response;
                }

                foreach (dynamic producesResponseTypeAttribute in producesResponseTypeAttributes)
                {
                    var returnType      = producesResponseTypeAttribute.Type;
                    var typeDescription = JsonObjectTypeDescription.FromType(returnType, method.ReturnParameter?.GetCustomAttributes(), Settings.DefaultEnumHandling);

                    var httpStatusCode = producesResponseTypeAttribute.StatusCode.ToString(CultureInfo.InvariantCulture);
                    operation.Responses[httpStatusCode] = new SwaggerResponse
                    {
                        Description   = xmlDescription ?? string.Empty,
                        IsNullableRaw = typeDescription.IsNullable,
                        Schema        = CreateAndAddSchema(returnType, typeDescription.IsNullable, null, schemaResolver, schemaDefinitionAppender)
                    };
                }
            }
            else
            {
                LoadDefaultReturnType(operation, method, xmlDescription, schemaResolver, schemaDefinitionAppender);
            }
        }
Example #22
0
        private void GeneratePropertiesAndInheritance(Type type, JsonSchema4 schema, JsonSchema4 rootSchema, ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
        {
            var properties = GetTypeProperties(type);

            foreach (var property in type.GetTypeInfo().DeclaredProperties.Where(p => properties == null || properties.Contains(p.Name)))
            {
                LoadProperty(type, property, schema, rootSchema, schemaDefinitionAppender, schemaResolver);
            }

            GenerateInheritance(type, schema, rootSchema, schemaDefinitionAppender, schemaResolver);
        }
Example #23
0
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        private void GenerateDictionary <TSchemaType>(Type type, JsonSchema4 rootSchema, TSchemaType schema, ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var genericTypeArguments = GetGenericTypeArguments(type);

            if (genericTypeArguments.Length != 2)
            {
                throw new InvalidOperationException("Could not find value type of dictionary type '" + type.FullName + "'.");
            }

            var valueType = genericTypeArguments[1];

            if (valueType == typeof(object))
            {
                schema.AdditionalPropertiesSchema = JsonSchema4.CreateAnySchema();
            }
            else
            {
                schema.AdditionalPropertiesSchema = Generate(valueType, rootSchema, null, schemaDefinitionAppender,
                                                             schemaResolver);
            }

            schema.AllowAdditionalProperties = true;
        }
        private JsonSchema4 CreateAndAddSchema(Type type, bool mayBeNull, IEnumerable <Attribute> parentAttributes,
                                               ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            if (type.Name == "Task`1")
            {
                type = type.GenericTypeArguments[0];
            }

            if (type.Name == "JsonResult`1")
            {
                type = type.GenericTypeArguments[0];
            }

            if (IsFileResponse(type))
            {
                return new JsonSchema4 {
                           Type = JsonObjectType.File
                }
            }
            ;

            var typeDescription = JsonObjectTypeDescription.FromType(type, parentAttributes, Settings.DefaultEnumHandling);

            if (typeDescription.Type.HasFlag(JsonObjectType.Object) && !typeDescription.IsDictionary)
            {
                if (type == typeof(object))
                {
                    return(new JsonSchema4
                    {
                        // IsNullable is directly set on SwaggerParameter or SwaggerResponse
                        Type = Settings.NullHandling == NullHandling.JsonSchema ? JsonObjectType.Object | JsonObjectType.Null : JsonObjectType.Object,
                        AllowAdditionalProperties = false
                    });
                }

                if (!schemaResolver.HasSchema(type, false))
                {
                    _schemaGenerator.Generate(type, schemaResolver, schemaDefinitionAppender);
                }

                if (mayBeNull)
                {
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        var schema = new JsonSchema4();
                        schema.OneOf.Add(new JsonSchema4 {
                            Type = JsonObjectType.Null
                        });
                        schema.OneOf.Add(new JsonSchema4 {
                            SchemaReference = schemaResolver.GetSchema(type, false)
                        });
                        return(schema);
                    }
                    else
                    {
                        // IsNullable is directly set on SwaggerParameter or SwaggerResponse
                        return(new JsonSchema4 {
                            SchemaReference = schemaResolver.GetSchema(type, false)
                        });
                    }
                }
                else
                {
                    return new JsonSchema4 {
                               SchemaReference = schemaResolver.GetSchema(type, false)
                    }
                };
            }

            if (typeDescription.Type.HasFlag(JsonObjectType.Array))
            {
                var itemType = type.GenericTypeArguments.Length == 0 ? type.GetElementType() : type.GenericTypeArguments[0];
                return(new JsonSchema4
                {
                    // IsNullable is directly set on SwaggerParameter or SwaggerResponse
                    Type = Settings.NullHandling == NullHandling.JsonSchema ? JsonObjectType.Array | JsonObjectType.Null : JsonObjectType.Array,
                    Item = CreateAndAddSchema(itemType, false, null, schemaResolver, schemaDefinitionAppender)
                });
            }

            return(_schemaGenerator.Generate(type, schemaResolver, schemaDefinitionAppender));
        }
    }
}
        private static void UpdateSchemaReferencePaths(object root, object obj, HashSet <object> checkedObjects, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            if (obj == null || obj is string)
            {
                return;
            }

            var schema = obj as JsonSchema4;

            if (schema != null && schema.SchemaReference != null)
            {
                schema.SchemaReferencePath = JsonPathUtilities.GetJsonPath(root, schema.SchemaReference.ActualSchema, schemaDefinitionAppender);
            }

            if (obj is IDictionary)
            {
                foreach (var item in ((IDictionary)obj).Values.OfType <object>().ToList())
                {
                    UpdateSchemaReferencePaths(root, item, checkedObjects, schemaDefinitionAppender);
                }
            }
            else if (obj is IEnumerable)
            {
                foreach (var item in ((IEnumerable)obj).OfType <object>().ToArray())
                {
                    UpdateSchemaReferencePaths(root, item, checkedObjects, schemaDefinitionAppender);
                }
            }

            if (!(obj is JToken))
            {
                foreach (var property in ReflectionCache.GetProperties(obj.GetType()).Where(p =>
                                                                                            p.CanRead && p.IsIndexer == false && p.MemberInfo is PropertyInfo &&
                                                                                            p.CustomAttributes.JsonIgnoreAttribute == null))
                {
                    var value = property.GetValue(obj);
                    if (value != null)
                    {
                        if (!checkedObjects.Contains(value))
                        {
                            checkedObjects.Add(value);
                            UpdateSchemaReferencePaths(root, value, checkedObjects, schemaDefinitionAppender);
                        }
                    }
                }
            }
        }
Example #26
0
        private void LoadPropertyOrField(MemberInfo property, Type propertyType, Type parentType, JsonSchema4 parentSchema, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            var attributes = property.GetCustomAttributes(inherit: true).OfType <Attribute>().ToArray();
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType, attributes, Settings.DefaultEnumHandling);

            if (IsPropertyIgnored(parentType, attributes) == false)
            {
                JsonProperty jsonProperty;

                if (propertyType.Name == "Nullable`1")
#if !LEGACY
                { propertyType = propertyType.GenericTypeArguments[0]; }
#else
                { propertyType = propertyType.GetGenericArguments()[0]; }
#endif

                var requiresSchemaReference = RequiresSchemaReference(propertyType, attributes);
                if (requiresSchemaReference)
                {
                    var propertySchema = Generate <JsonSchema4>(propertyType, attributes, schemaResolver, schemaDefinitionAppender);

                    // The schema is automatically added to Definitions if it is missing in JsonPathUtilities.GetJsonPath()
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        jsonProperty = new JsonProperty();
                        jsonProperty.OneOf.Add(new JsonSchema4
                        {
                            SchemaReference = propertySchema.ActualSchema
                        });
                    }
                    else
                    {
                        jsonProperty = new JsonProperty
                        {
                            SchemaReference = propertySchema.ActualSchema
                        };
                    }
                }
                else
                {
                    jsonProperty = Generate <JsonProperty>(propertyType, attributes, schemaResolver, schemaDefinitionAppender);
                }

                var propertyName = JsonPathUtilities.GetPropertyName(property, Settings.DefaultPropertyNameHandling);
                if (parentSchema.Properties.ContainsKey(propertyName))
                {
                    throw new InvalidOperationException("The JSON property '" + propertyName + "' is defined multiple times on type '" + parentType.FullName + "'.");
                }

                parentSchema.Properties.Add(propertyName, jsonProperty);

                var requiredAttribute     = attributes.TryGetIfAssignableTo("System.ComponentModel.DataAnnotations.RequiredAttribute");
                var jsonPropertyAttribute = attributes.OfType <JsonPropertyAttribute>().SingleOrDefault();

                var hasJsonNetAttributeRequired = jsonPropertyAttribute != null && (
                    jsonPropertyAttribute.Required == Required.Always ||
                    jsonPropertyAttribute.Required == Required.AllowNull);

                var isDataContractMemberRequired = GetDataMemberAttribute(parentType, attributes)?.IsRequired == true;

                var hasRequiredAttribute = requiredAttribute != null;
                if (hasRequiredAttribute || isDataContractMemberRequired || hasJsonNetAttributeRequired)
                {
                    parentSchema.RequiredProperties.Add(propertyName);
                }

                var isJsonNetAttributeNullable = jsonPropertyAttribute != null && jsonPropertyAttribute.Required == Required.AllowNull;

                var isNullable = !hasRequiredAttribute && !isDataContractMemberRequired && (propertyTypeDescription.IsNullable || isJsonNetAttributeNullable);
                if (isNullable)
                {
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        if (requiresSchemaReference)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else if (jsonProperty.Type == JsonObjectType.None)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.None
                            });
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else
                        {
                            jsonProperty.Type = jsonProperty.Type | JsonObjectType.Null;
                        }
                    }
                }
                else if (Settings.NullHandling == NullHandling.Swagger)
                {
                    if (!parentSchema.RequiredProperties.Contains(propertyName))
                    {
                        parentSchema.RequiredProperties.Add(propertyName);
                    }
                }

                dynamic readOnlyAttribute = attributes.TryGetIfAssignableTo("System.ComponentModel.ReadOnlyAttribute");
                if (readOnlyAttribute != null)
                {
                    jsonProperty.IsReadOnly = readOnlyAttribute.IsReadOnly;
                }

                jsonProperty.Description = GetDescription(property, attributes);

                ApplyPropertyAnnotations(jsonProperty, parentType, attributes, propertyTypeDescription);
            }
        }
Example #27
0
        private void LoadProperty(Type parentType, PropertyInfo property, JsonSchema4 parentSchema, JsonSchema4 rootSchema,
                                  ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
        {
            var propertyType            = property.PropertyType;
            var propertyTypeDescription = JsonObjectTypeDescription.FromType(propertyType, property.GetCustomAttributes(), Settings.DefaultEnumHandling);

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

            if (IsPropertyIgnored(parentType, attributes) == false)
            {
                JsonProperty jsonProperty;

                if (propertyType.Name == "Nullable`1")
                {
                    propertyType = propertyType.GenericTypeArguments[0];
                }

                var useSchemaReference = !propertyTypeDescription.IsDictionary && (propertyTypeDescription.Type.HasFlag(JsonObjectType.Object) || propertyTypeDescription.IsEnum);
                if (useSchemaReference)
                {
                    // schema is automatically added to Definitions if it is missing in JsonPathUtilities.GetJsonPath()

                    var propertySchema = Generate(propertyType, rootSchema,
                                                  property.GetCustomAttributes(), schemaDefinitionAppender, schemaResolver);

                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        jsonProperty = new JsonProperty();
                        jsonProperty.OneOf.Add(new JsonSchema4
                        {
                            SchemaReference = propertySchema.ActualSchema
                        });
                    }
                    else
                    {
                        jsonProperty = new JsonProperty
                        {
                            SchemaReference = propertySchema.ActualSchema
                        };
                    }
                }
                else
                {
                    jsonProperty = Generate <JsonProperty>(propertyType, rootSchema, property.GetCustomAttributes(), schemaDefinitionAppender, schemaResolver);
                    propertyTypeDescription.ApplyType(jsonProperty);
                }

                var propertyName = JsonPathUtilities.GetPropertyName(property);
                parentSchema.Properties.Add(propertyName, jsonProperty);

                var requiredAttribute     = TryGetAttribute(attributes, "System.ComponentModel.DataAnnotations.RequiredAttribute");
                var jsonPropertyAttribute = property.GetCustomAttribute <JsonPropertyAttribute>();

                var hasJsonNetAttributeRequired = jsonPropertyAttribute != null && (
                    jsonPropertyAttribute.Required == Required.Always ||
                    jsonPropertyAttribute.Required == Required.AllowNull);

                var hasRequiredAttribute = requiredAttribute != null;
                if (hasRequiredAttribute || hasJsonNetAttributeRequired)
                {
                    parentSchema.RequiredProperties.Add(propertyName);
                }

                var isJsonNetAttributeNullable = jsonPropertyAttribute != null && jsonPropertyAttribute.Required == Required.AllowNull;

                var isNullable = !hasRequiredAttribute && (propertyTypeDescription.IsNullable || isJsonNetAttributeNullable);
                if (isNullable)
                {
                    if (Settings.NullHandling == NullHandling.JsonSchema)
                    {
                        if (useSchemaReference)
                        {
                            jsonProperty.OneOf.Add(new JsonSchema4 {
                                Type = JsonObjectType.Null
                            });
                        }
                        else
                        {
                            jsonProperty.Type = jsonProperty.Type | JsonObjectType.Null;
                        }
                    }
                }
                else if (Settings.NullHandling == NullHandling.Swagger)
                {
                    if (!parentSchema.RequiredProperties.Contains(propertyName))
                    {
                        parentSchema.RequiredProperties.Add(propertyName);
                    }
                }

                dynamic readOnlyAttribute = TryGetAttribute(attributes, "System.ComponentModel.ReadOnlyAttribute");
                if (readOnlyAttribute != null)
                {
                    jsonProperty.IsReadOnly = readOnlyAttribute.IsReadOnly;
                }

                jsonProperty.Description = GetDescription(property, attributes);

                ApplyPropertyAnnotations(jsonProperty, attributes, propertyTypeDescription);
            }
        }
Example #28
0
 /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
 /// <param name="type">The type.</param>
 /// <param name="schemaResolver"></param>
 /// <param name="schemaDefinitionAppender"></param>
 /// <returns>The schema.</returns>
 /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
 public JsonSchema4 Generate(Type type, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
 {
     return(Generate <JsonSchema4>(type, null, schemaResolver, schemaDefinitionAppender));
 }
Example #29
0
 /// <summary>Generates a <see cref="JsonSchema4" /> object for the given type and adds the mapping to the given resolver.</summary>
 /// <param name="type">The type.</param>
 /// <param name="rootSchema">The root schema.</param>
 /// <param name="parentAttributes">The parent property or parameter attributes.</param>
 /// <param name="schemaDefinitionAppender">The schema definition appender.</param>
 /// <param name="schemaResolver">The schema resolver.</param>
 /// <returns>The schema.</returns>
 /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
 public JsonSchema4 Generate(Type type, JsonSchema4 rootSchema, IEnumerable <Attribute> parentAttributes,
                             ISchemaDefinitionAppender schemaDefinitionAppender, ISchemaResolver schemaResolver)
 {
     return(Generate <JsonSchema4>(type, rootSchema, parentAttributes, schemaDefinitionAppender, schemaResolver));
 }
        /// <summary>Generates the properties for the given type and schema.</summary>
        /// <typeparam name="TSchemaType">The type of the schema type.</typeparam>
        /// <param name="type">The types.</param>
        /// <param name="schema">The properties</param>
        /// <param name="schemaResolver"></param>
        /// <param name="schemaDefinitionAppender"></param>
        protected override void GenerateObject <TSchemaType>(Type type, TSchemaType schema, ISchemaResolver schemaResolver, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            if (_isRootType)
            {
                _isRootType = false;
                base.GenerateObject(type, schema, schemaResolver, schemaDefinitionAppender);
                _isRootType = true;
            }
            else
            {
                if (!schemaResolver.HasSchema(type, false))
                {
                    _isRootType = true;
                    Generate(type, schemaResolver, schemaDefinitionAppender);
                    _isRootType = false;
                }

                schema.SchemaReference = schemaResolver.GetSchema(type, false);
            }
        }
Example #31
0
        private static void UpdateSchemaReferencePaths(object root, object obj, List <object> checkedObjects, ISchemaDefinitionAppender schemaDefinitionAppender)
        {
            if (obj == null || obj is string)
            {
                return;
            }

            var schema = obj as JsonSchema4;

            if (schema != null && schema.SchemaReference != null)
            {
                schema.SchemaReferencePath = JsonPathUtilities.GetJsonPath(root, schema.SchemaReference.ActualSchema, schemaDefinitionAppender);
            }

            if (obj is IDictionary)
            {
                foreach (var item in ((IDictionary)obj).Values.OfType <object>().ToList())
                {
                    UpdateSchemaReferencePaths(root, item, checkedObjects, schemaDefinitionAppender);
                }
            }
            else if (obj is IEnumerable)
            {
                foreach (var item in (IEnumerable)obj)
                {
                    UpdateSchemaReferencePaths(root, item, checkedObjects, schemaDefinitionAppender);
                }
            }
            else
            {
                foreach (var property in obj.GetType().GetRuntimeProperties().Where(p => p.CanRead && p.GetCustomAttribute <JsonIgnoreAttribute>() == null))
                {
                    var value = property.GetValue(obj);
                    if (value != null)
                    {
                        if (!checkedObjects.Contains(value))
                        {
                            checkedObjects.Add(value);
                            UpdateSchemaReferencePaths(root, value, checkedObjects, schemaDefinitionAppender);
                        }
                    }
                }
            }
        }