Exemple #1
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;
        }
Exemple #2
0
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        private async Task GenerateDictionaryAsync <TSchemaType>(TSchemaType schema, Type type, JsonSchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var genericTypeArguments = type.GetGenericTypeArguments();

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

            if (valueType == typeof(object))
            {
                schema.AdditionalPropertiesSchema = JsonSchema4.CreateAnySchema();
            }
            else
            {
                var additionalPropertiesSchema = await GenerateAsync(valueType, schemaResolver).ConfigureAwait(false);

                var valueTypeDescription = Settings.ReflectionService.GetDescription(valueType, null, Settings);
                if (valueTypeDescription.RequiresSchemaReference(Settings.TypeMappers))
                {
                    schema.AdditionalPropertiesSchema = new JsonSchema4
                    {
                        Reference = additionalPropertiesSchema
                    };
                }
                else
                {
                    schema.AdditionalPropertiesSchema = additionalPropertiesSchema;
                }
            }

            schema.AllowAdditionalProperties = true;
        }
Exemple #3
0
        private async Task GenerateArray <TSchemaType>(
            TSchemaType schema, Type type, JsonTypeDescription typeDescription, JsonSchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            typeDescription.ApplyType(schema);

            var itemType = type.GetEnumerableItemType();

            if (itemType != null)
            {
                schema.Item = await GenerateWithReferenceAndNullability <JsonSchema4>(
#pragma warning disable 1998
                    itemType, null, false, schemaResolver, async (s, r) =>
#pragma warning restore 1998
                {
                    if (Settings.GenerateXmlObjects)
                    {
                        s.GenerateXmlObjectForItemType(itemType);
                    }
                }).ConfigureAwait(false);
            }
            else
            {
                schema.Item = JsonSchema4.CreateAnySchema();
            }
        }
        /// <exception cref="InvalidOperationException">Could not find value type of dictionary type.</exception>
        private async Task GenerateDictionaryAsync <TSchemaType>(Type type, TSchemaType schema, JsonSchemaResolver schemaResolver)
            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
            {
                var additionalPropertiesSchema = await GenerateAsync(valueType, schemaResolver).ConfigureAwait(false);

                if (RequiresSchemaReference(valueType, null))
                {
                    schema.AdditionalPropertiesSchema = new JsonSchema4
                    {
                        SchemaReference = additionalPropertiesSchema
                    };
                }
                else
                {
                    schema.AdditionalPropertiesSchema = additionalPropertiesSchema;
                }
            }

            schema.AllowAdditionalProperties = true;
        }
Exemple #5
0
        private TSchemaType HandleSpecialTypes <TSchemaType>(Type type)
            where TSchemaType : JsonSchema4, new()
        {
            if (type == typeof(JObject) || type == typeof(JToken) || type == typeof(object))
            {
                return(JsonSchema4.CreateAnySchema <TSchemaType>());
            }

            return(null);
        }
Exemple #6
0
        private TSchemaType HandleSpecialTypes <TSchemaType>(Type type, ISchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            var typeMapper = Settings.TypeMappers.FirstOrDefault(m => m.MappedType == type);

            if (typeMapper != null)
            {
                var schema = typeMapper.GetSchema <TSchemaType>(this, schemaResolver);
                if (schema != null)
                {
                    return(schema);
                }
            }

            if (type == typeof(JObject) || type == typeof(JToken) || type == typeof(object))
            {
                return(JsonSchema4.CreateAnySchema <TSchemaType>());
            }

            return(null);
        }
Exemple #7
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;
        }
Exemple #8
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);
        }
Exemple #9
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);
        }
Exemple #10
0
        /// <summary>Generates and appends a schema from a given type.</summary>
        /// <param name="type">The type.</param>
        /// <param name="mayBeNull">if set to <c>true</c> [may be null].</param>
        /// <param name="parentAttributes">The parent attributes.</param>
        /// <returns></returns>
        public async Task <JsonSchema4> GenerateAndAppendSchemaFromTypeAsync(Type type, bool mayBeNull, IEnumerable <Attribute> parentAttributes)
        {
            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, ResolveContract(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))
                {
                    await _schemaGenerator.GenerateAsync(type, _schemaResolver).ConfigureAwait(false);
                }

                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
                    {
                        // TODO: Fix this bad design
                        // IsNullable must be 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 jsonType = _settings.NullHandling == NullHandling.JsonSchema
                    ? JsonObjectType.Array | JsonObjectType.Null
                    : JsonObjectType.Array;

                var itemType   = type.GetEnumerableItemType();
                var itemSchema = itemType != null
                    ? await GenerateAndAppendSchemaFromTypeAsync(itemType, false, null).ConfigureAwait(false)
                    : JsonSchema4.CreateAnySchema();

                return(new JsonSchema4
                {
                    Type = jsonType,
                    Item = itemSchema
                });

                // TODO: Fix this bad design
                // IsNullable must be directly set on SwaggerParameter or SwaggerResponse
            }

            return(await _schemaGenerator.GenerateAsync(type, _schemaResolver).ConfigureAwait(false));
        }
        /// <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.</typeparam>
        /// <param name="type">The type.</param>
        /// <param name="parentAttributes">The parent property or parameter attributes.</param>
        /// <param name="schema">The schema.</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 virtual async Task GenerateAsync <TSchemaType>(Type type, IEnumerable <Attribute> parentAttributes, TSchemaType schema, JsonSchemaResolver schemaResolver)
            where TSchemaType : JsonSchema4, new()
        {
            if (await TryHandleSpecialTypesAsync(type, schema, schemaResolver, parentAttributes))
            {
                await ApplySchemaProcessorsAsync(schema, schemaResolver);

                return;
            }

            if (schemaResolver.RootObject == schema)
            {
                schema.Title = Settings.SchemaNameGenerator.Generate(type);
            }

            ApplyExtensionDataAttributes(type, schema, parentAttributes);

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

            if (typeDescription.Type.HasFlag(JsonObjectType.Object))
            {
                if (typeDescription.IsDictionary)
                {
                    typeDescription.ApplyType(schema);
                    await GenerateDictionaryAsync(type, schema, schemaResolver).ConfigureAwait(false);
                }
                else
                {
                    if (schemaResolver.HasSchema(type, false))
                    {
                        schema.SchemaReference = schemaResolver.GetSchema(type, false);
                    }
                    else if (schema.GetType() == typeof(JsonSchema4))
                    {
                        typeDescription.ApplyType(schema);
                        schema.Description = await type.GetTypeInfo().GetDescriptionAsync(type.GetTypeInfo().GetCustomAttributes()).ConfigureAwait(false);
                        await GenerateObjectAsync(type, contract, schema, schemaResolver).ConfigureAwait(false);
                    }
                    else
                    {
                        schema.SchemaReference = await GenerateAsync(type, parentAttributes, schemaResolver).ConfigureAwait(false);
                    }
                }
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                var isIntegerEnumeration = typeDescription.Type == JsonObjectType.Integer;
                if (schemaResolver.HasSchema(type, isIntegerEnumeration))
                {
                    schema.SchemaReference = schemaResolver.GetSchema(type, isIntegerEnumeration);
                }
                else if (schema.GetType() == typeof(JsonSchema4))
                {
                    LoadEnumerations(type, schema, typeDescription);

                    typeDescription.ApplyType(schema);
                    schema.Description = await type.GetXmlSummaryAsync().ConfigureAwait(false);

                    schemaResolver.AddSchema(type, isIntegerEnumeration, schema);
                }
                else
                {
                    schema.SchemaReference = await GenerateAsync(type, parentAttributes, schemaResolver).ConfigureAwait(false);
                }
            }
            else if (typeDescription.Type.HasFlag(JsonObjectType.Array))
            {
                typeDescription.ApplyType(schema);

                var itemType = type.GetEnumerableItemType();
                if (itemType != null)
                {
                    schema.Item = await GenerateWithReferenceAsync(schemaResolver, itemType).ConfigureAwait(false);
                }
                else
                {
                    schema.Item = JsonSchema4.CreateAnySchema();
                }
            }
            else
            {
                typeDescription.ApplyType(schema);
            }

            await ApplySchemaProcessorsAsync(schema, schemaResolver);
        }