private static IOpenApiAny ConvertToOpenApiType(Type memberType, OpenApiSchema schema, string stringValue)
        {
            object typedValue;

            try
            {
                typedValue = TypeDescriptor.GetConverter(memberType).ConvertFrom(
                    context: null,
                    culture: CultureInfo.InvariantCulture,
                    stringValue);
            }
            catch (Exception)
            {
                return(null);
            }

            return(OpenApiAnyFactory.CreateFor(schema, typedValue));
        }
예제 #2
0
        private OpenApiSchema GeneratePrimitiveSchema(DataContract dataContract)
        {
            var schema = new OpenApiSchema
            {
                Type   = dataContract.DataType.ToString().ToLower(CultureInfo.InvariantCulture),
                Format = dataContract.DataFormat
            };

            if (dataContract.EnumValues != null)
            {
                schema.Enum = dataContract.EnumValues
                              .Distinct()
                              .Select(value => OpenApiAnyFactory.CreateFor(schema, value))
                              .ToList();
            }

            return(schema);
        }
예제 #3
0
        private OpenApiSchema GenerateSchemaFromFormParameters(
            IEnumerable <ApiParameterDescription> formParameters,
            SchemaRepository schemaRepository)
        {
            var properties            = new Dictionary <string, OpenApiSchema>();
            var requiredPropertyNames = new List <string>();

            foreach (var formParameter in formParameters)
            {
                var name = _options.DescribeAllParametersInCamelCase
                    ? formParameter.Name.ToCamelCase()
                    : formParameter.Name;

                var schema = (formParameter.ModelMetadata != null)
                    ? _schemaGenerator.GenerateSchema(formParameter.Type, schemaRepository)
                    : new OpenApiSchema {
                    Type = "string"
                };

                var defaultValue = formParameter.CustomAttributes().OfType <DefaultValueAttribute>().FirstOrDefault()?.Value
                                   ?? formParameter.ParameterInfo()?.DefaultValue;

                if (defaultValue != null && schema.Reference == null)
                {
                    schema.Default = OpenApiAnyFactory.TryCreateFor(schema, defaultValue, out IOpenApiAny openApiAny)
                        ? openApiAny
                        : null;
                }

                properties.Add(name, schema);

                if (formParameter.IsFromPath() || formParameter.CustomAttributes().Any(attr => RequiredAttributeTypes.Contains(attr.GetType())))
                {
                    requiredPropertyNames.Add(name);
                }
            }

            return(new OpenApiSchema
            {
                Type = "object",
                Properties = properties,
                Required = new SortedSet <string>(requiredPropertyNames)
            });
        }
        private OpenApiSchema GenerateEnumSchema(JsonPrimitiveContract jsonPrimitiveContract)
        {
            var stringEnumConverter = (jsonPrimitiveContract.Converter as StringEnumConverter)
                                      ?? _serializerSettings.Converters.OfType <StringEnumConverter>().FirstOrDefault();

            var describeAsString = Options.DescribeAllEnumsAsStrings ||
                                   (stringEnumConverter != null);

            var describeInCamelCase = Options.DescribeStringEnumsInCamelCase ||
                                      (stringEnumConverter != null && stringEnumConverter.CamelCaseText);

            var enumType           = jsonPrimitiveContract.UnderlyingType;
            var enumUnderlyingType = describeAsString ? typeof(string) : enumType.GetEnumUnderlyingType();

            var schema = FactoryMethodMap[enumUnderlyingType]();

            if (describeAsString)
            {
                schema.Enum = enumType.GetEnumNames()
                              .Distinct()
                              .Select(name =>
                {
                    name = describeInCamelCase ? name.ToCamelCase() : name;
                    return((IOpenApiAny)(new OpenApiString(name)));
                })
                              .ToList();
            }
            else
            {
                schema.Enum = enumType.GetEnumValues()
                              .Cast <object>()
                              .Distinct()
                              .Select(value =>
                {
                    value = Convert.ChangeType(value, enumUnderlyingType);
                    return(OpenApiAnyFactory.TryCreateFor(schema, value, out IOpenApiAny openApiAny) ? openApiAny : null);
                })
                              .ToList();
            }

            return(schema);
        }
예제 #5
0
        private OpenApiSchema GeneratePrimitiveSchema(DataContract dataContract)
        {
            var schema = new OpenApiSchema
            {
                Type   = dataContract.DataType.ToString().ToLower(CultureInfo.InvariantCulture),
                Format = dataContract.DataFormat
            };

            if (dataContract.UnderlyingType.IsEnum)
            {
                schema.Enum = dataContract.UnderlyingType.GetEnumValues()
                              .Cast <object>()
                              .Distinct()
                              .Select(value => _serializerBehavior.Serialize(value))
                              .Select(json => OpenApiAnyFactory.CreateFromJson(json))
                              .ToList();
            }

            return(schema);
        }
예제 #6
0
        private void ApplyParamTags(OpenApiRequestBody requestBody, RequestBodyFilterContext context, ParameterInfo parameterInfo)
        {
            if (!(parameterInfo.Member is MethodInfo methodInfo))
            {
                return;
            }

            // If method is from a constructed generic type, look for comments from the generic type method
            var targetMethod = methodInfo.DeclaringType.IsConstructedGenericType
                ? methodInfo.GetUnderlyingGenericTypeMethod()
                : methodInfo;

            if (targetMethod == null)
            {
                return;
            }

            var methodMemberName = XmlCommentsNodeNameHelper.GetMemberNameForMethod(targetMethod);
            var paramNode        = _xmlNavigator.SelectSingleNode(
                $"/doc/members/member[@name='{methodMemberName}']/param[@name='{parameterInfo.Name}']");

            if (paramNode != null)
            {
                requestBody.Description = XmlCommentsTextHelper.Humanize(paramNode.InnerXml);

                var example = paramNode.GetAttribute("example", "");
                if (string.IsNullOrEmpty(example))
                {
                    return;
                }

                foreach (var mediaType in requestBody.Content.Values)
                {
                    var exampleAsJson = (mediaType.Schema?.ResolveType(context.SchemaRepository) == "string")
                        ? $"\"{example}\""
                        : example;

                    mediaType.Example = OpenApiAnyFactory.CreateFromJson(exampleAsJson);
                }
            }
        }
예제 #7
0
        private OpenApiSchema GenerateSchemaForParameter(
            Type modelType,
            SchemaRepository schemaRepository,
            ParameterInfo parameterInfo)
        {
            var dataContract = GetDataContractFor(modelType);

            var schema = _generatorOptions.UseOneOfForPolymorphism && IsBaseTypeWithKnownTypesDefined(dataContract, out var knownTypesDataContracts)
                ? GeneratePolymorphicSchema(dataContract, schemaRepository, knownTypesDataContracts)
                : GenerateConcreteSchema(dataContract, schemaRepository);

            if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema.Reference != null)
            {
                schema.AllOf = new[] { new OpenApiSchema {
                                           Reference = schema.Reference
                                       } };
                schema.Reference = null;
            }

            if (schema.Reference == null)
            {
                var customAttributes = parameterInfo.GetCustomAttributes();

                var defaultValue = parameterInfo.HasDefaultValue
                    ? parameterInfo.DefaultValue
                    : customAttributes.OfType <DefaultValueAttribute>().FirstOrDefault()?.Value;

                if (defaultValue != null)
                {
                    var defaultAsJson = dataContract.JsonConverter(defaultValue);
                    schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson);
                }

                schema.ApplyValidationAttributes(customAttributes);

                ApplyFilters(schema, modelType, schemaRepository, parameterInfo: parameterInfo);
            }

            return(schema);
        }
        private void ApplyParameterMetadata(OpenApiSchema schema, Type type, ParameterInfo parameterInfo)
        {
            if (schema.Reference != null && _generatorOptions.UseAllOfToExtendReferenceSchemas)
            {
                schema.AllOf = new[] { new OpenApiSchema {
                                           Reference = schema.Reference
                                       } };
                schema.Reference = null;
            }

            if (schema.Reference == null)
            {
                schema.Nullable = type.IsReferenceOrNullableType();

                schema.ApplyCustomAttributes(parameterInfo.GetCustomAttributes());

                if (parameterInfo.HasDefaultValue)
                {
                    schema.Default = OpenApiAnyFactory.CreateFor(schema, parameterInfo.DefaultValue);
                }
            }
        }
예제 #9
0
        public override OpenApiSchema CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
        {
            var isNullable = type.IsNullable(out Type innerType);

            var enumType = isNullable
                ? innerType
                : type;

            //Test to determine if the serializer will treat as string or not
            var describeAsString = JsonSerializer.Serialize(enumType.GetEnumValues().GetValue(0), _serializerOptions).StartsWith("\"");

            var schema = describeAsString
                ? EnumTypeMap[typeof(string)]()
                : EnumTypeMap[enumType.GetEnumUnderlyingType()]();

            if (describeAsString)
            {
                schema.Enum = enumType.GetEnumValues()
                              .Cast <object>()
                              .Select(value =>
                {
                    var stringValue = JsonSerializer.Serialize(value, _serializerOptions).Replace("\"", string.Empty);
                    return(OpenApiAnyFactory.CreateFor(schema, stringValue));
                })
                              .ToList();
            }
            else
            {
                schema.Enum = enumType.GetEnumValues()
                              .Cast <object>()
                              .Select(value => OpenApiAnyFactory.CreateFor(schema, value))
                              .ToList();
            }

            schema.Nullable = isNullable;

            return(schema);
        }
예제 #10
0
        private void ApplyParameterMetadata(OpenApiSchema schema, Type type, ParameterInfo parameterInfo)
        {
            if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema.Reference != null)
            {
                schema.AllOf = new[] { new OpenApiSchema {
                                           Reference = schema.Reference
                                       } };
                schema.Reference = null;
            }

            if (schema.Reference == null)
            {
                schema.Nullable = type.IsReferenceOrNullableType();

                if (parameterInfo.HasDefaultValue)
                {
                    var defaultAsJson = _serializerBehavior.Serialize(parameterInfo.DefaultValue);
                    schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson);
                }

                schema.ApplyValidationAttributes(parameterInfo.GetCustomAttributes());
            }
        }
예제 #11
0
        private void ApplyMemberMetadata(OpenApiSchema schema, Type type, MemberInfo memberInfo)
        {
            if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema.Reference != null)
            {
                schema.AllOf = new[] { new OpenApiSchema {
                                           Reference = schema.Reference
                                       } };
                schema.Reference = null;
            }

            if (schema.Reference == null)
            {
                var customAttributes = memberInfo.GetInlineAndMetadataAttributes();

                schema.Nullable = type.IsReferenceOrNullableType();

                if (!_generatorOptions.SuppressNonNullableReferenceTypes && memberInfo.IsNonNullable())
                {
                    schema.Nullable = false;
                }

                var defaultValueAttribute = customAttributes.OfType <DefaultValueAttribute>().FirstOrDefault();
                if (defaultValueAttribute != null)
                {
                    var defaultAsJson = _serializerBehavior.Serialize(defaultValueAttribute.Value);
                    schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson); // TODO: address assumption that serializer returns JSON
                }

                var obsoleteAttribute = customAttributes.OfType <ObsoleteAttribute>().FirstOrDefault();
                if (obsoleteAttribute != null)
                {
                    schema.Deprecated = true;
                }

                schema.ApplyValidationAttributes(customAttributes);
            }
        }
예제 #12
0
        private static IOpenApiAny ConvertToOpenApiType(Type memberType, OpenApiSchema schema, string stringValue)
        {
            object typedValue;
            var    culture = CultureInfo.CurrentCulture;

            CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;

            try
            {
                typedValue = TypeDescriptor.GetConverter(memberType).ConvertFrom(stringValue);
            }
            catch (Exception)
            {
                return(null);
            }
            finally
            {
                CultureInfo.CurrentCulture = culture;
            }

            return(OpenApiAnyFactory.TryCreateFor(schema, typedValue, out IOpenApiAny openApiAny)
                ? openApiAny
                : null);
        }
        private void ApplyPropertyTags(OpenApiParameter parameter, PropertyInfo propertyInfo)
        {
            var propertyMemberName = XmlCommentsNodeNameHelper.GetMemberNameForFieldOrProperty(propertyInfo);
            var propertyNode       = _xmlNavigator.SelectSingleNode($"/doc/members/member[@name='{propertyMemberName}']");

            if (propertyNode == null)
            {
                return;
            }

            var summaryNode = propertyNode.SelectSingleNode("summary");

            if (summaryNode != null)
            {
                parameter.Description = XmlCommentsTextHelper.Humanize(summaryNode.InnerXml);
            }

            var exampleNode = propertyNode.SelectSingleNode("example");

            if (exampleNode != null)
            {
                parameter.Example = OpenApiAnyFactory.CreateFromJson(exampleNode.InnerXml);
            }
        }
예제 #14
0
        private OpenApiSchema GeneratePropertySchema(
            JsonProperty jsonProperty,
            MemberInfo memberInfo,
            object[] attributes,
            SchemaRepository schemaRepository)
        {
            var schema = RootGenerator.GenerateSchema(jsonProperty.PropertyType, schemaRepository);

            schema.WriteOnly = jsonProperty.Writable && !jsonProperty.Readable;
            schema.ReadOnly  = jsonProperty.Readable && !jsonProperty.Writable;

            foreach (var attribute in attributes)
            {
                if (attribute is DefaultValueAttribute defaultValue)
                {
                    schema.Default = OpenApiAnyFactory.TryCreateFor(schema, defaultValue.Value, out IOpenApiAny openApiAny)
                        ? openApiAny
                        : schema.Default;
                }
                else if (attribute is RegularExpressionAttribute regex)
                {
                    schema.Pattern = regex.Pattern;
                }
                else if (attribute is RangeAttribute range)
                {
                    schema.Maximum = decimal.TryParse(range.Maximum.ToString(), out decimal maximum)
                        ? maximum
                        : schema.Maximum;

                    schema.Minimum = decimal.TryParse(range.Minimum.ToString(), out decimal minimum)
                        ? minimum
                        : schema.Minimum;
                }
                else if (attribute is MinLengthAttribute minLength)
                {
                    schema.MinLength = minLength.Length;
                }
                else if (attribute is MaxLengthAttribute maxLength)
                {
                    schema.MaxLength = maxLength.Length;
                }
                else if (attribute is StringLengthAttribute stringLength)
                {
                    schema.MinLength = stringLength.MinimumLength;
                    schema.MaxLength = stringLength.MaximumLength;
                }
                else if (attribute is EmailAddressAttribute)
                {
                    schema.Format = "email";
                }
                else if (attribute is CreditCardAttribute)
                {
                    schema.Format = "credit-card";
                }
                else if (attribute is PhoneAttribute)
                {
                    schema.Format = "tel";
                }
                else if (attribute is DataTypeAttribute dataTypeAttribute && schema.Type == "string")
                {
                    schema.Format = DataTypeFormatMap.TryGetValue(dataTypeAttribute.DataType, out string format)
                        ? format
                        : schema.Format;
                }
            }

            return(schema);
        }
        private OpenApiSchema GenerateSchemaForMember(
            Type modelType,
            SchemaRepository schemaRepository,
            MemberInfo memberInfo,
            DataProperty dataProperty = null)
        {
            var dataContract = GetDataContractFor(modelType);

            var schema = _generatorOptions.UseOneOfForPolymorphism && IsBaseTypeWithKnownTypesDefined(dataContract, out var knownTypesDataContracts)
                ? GeneratePolymorphicSchema(dataContract, schemaRepository, knownTypesDataContracts)
                : GenerateConcreteSchema(dataContract, schemaRepository);

            if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema.Reference != null)
            {
                schema.AllOf = new[] { new OpenApiSchema {
                                           Reference = schema.Reference
                                       } };
                schema.Reference = null;
            }

            if (schema.Reference == null)
            {
                var customAttributes = memberInfo.GetInlineAndMetadataAttributes();

                // Nullable, ReadOnly & WriteOnly are only relevant for Schema "properties" (i.e. where dataProperty is non-null)
                if (dataProperty != null)
                {
                    schema.Nullable = _generatorOptions.SupportNonNullableReferenceTypes
                        ? dataProperty.IsNullable && !customAttributes.OfType <RequiredAttribute>().Any() && !memberInfo.IsNonNullableReferenceType()
                        : dataProperty.IsNullable && !customAttributes.OfType <RequiredAttribute>().Any();

                    schema.ReadOnly  = dataProperty.IsReadOnly;
                    schema.WriteOnly = dataProperty.IsWriteOnly;
                }

                var defaultValueAttribute = customAttributes.OfType <DefaultValueAttribute>().FirstOrDefault();
                if (defaultValueAttribute != null)
                {
                    var defaultAsJson = dataContract.JsonConverter(defaultValueAttribute.Value);
                    schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson);
                }

                var obsoleteAttribute = customAttributes.OfType <ObsoleteAttribute>().FirstOrDefault();
                if (obsoleteAttribute != null)
                {
                    schema.Deprecated = true;
                }

                // NullableAttribute behaves diffrently for Dictionaries
                if (modelType.IsGenericType && modelType.GetGenericTypeDefinition() == typeof(Dictionary <,>))
                {
                    schema.AdditionalProperties.Nullable = !memberInfo.IsDictionaryValueNonNullable();
                }

                schema.ApplyValidationAttributes(customAttributes);

                ApplyFilters(schema, modelType, schemaRepository, memberInfo: memberInfo);
            }

            return(schema);
        }
 private static void ApplyDefaultValueAttribute(OpenApiSchema schema, DefaultValueAttribute defaultValueAttribute)
 {
     schema.Default = OpenApiAnyFactory.CreateFor(schema, defaultValueAttribute.Value);
 }