Skip to content

Commit

Permalink
Unify implementations
Browse files Browse the repository at this point in the history
Use the same implementation for coercing the default value to the correct type for both `[DefaultValue]` and default method parameters.
  • Loading branch information
martincostello committed May 19, 2024
1 parent 5e22cd0 commit b10358c
Showing 1 changed file with 25 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;

namespace Swashbuckle.AspNetCore.SwaggerGen
Expand Down Expand Up @@ -80,25 +81,7 @@ private OpenApiSchema GenerateSchemaForMember(
var defaultValueAttribute = customAttributes.OfType<DefaultValueAttribute>().FirstOrDefault();
if (defaultValueAttribute != null)
{
var defaultValue = defaultValueAttribute.Value;

// If the types do not match (e.g. a default which is an integer is specified for a double),
// attempt to coerce the default value to the correct type so that it can be serialized correctly.
// See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2885.
if (defaultValue?.GetType() != modelType)
{
try
{
defaultValue = Convert.ChangeType(defaultValue, modelType);
}
catch (Exception)
{
// Conversion failed, use the original default value anyway
}
}

var defaultAsJson = dataContract.JsonConverter(defaultValue);
schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson);
schema.Default = GenerateDefaultValue(dataContract, modelType, defaultValueAttribute.Value);
}

var obsoleteAttribute = customAttributes.OfType<ObsoleteAttribute>().FirstOrDefault();
Expand All @@ -107,8 +90,9 @@ private OpenApiSchema GenerateSchemaForMember(
schema.Deprecated = true;
}

// NullableAttribute behaves diffrently for Dictionaries
if (schema.AdditionalPropertiesAllowed && modelType.IsGenericType && modelType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
// NullableAttribute behaves differently for Dictionaries
if (schema.AdditionalPropertiesAllowed && modelType.IsGenericType &&
modelType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
schema.AdditionalProperties.Nullable = !memberInfo.IsDictionaryValueNonNullable();
}
Expand Down Expand Up @@ -149,16 +133,7 @@ private OpenApiSchema GenerateSchemaForParameter(

if (defaultValue != null)
{
var exampleContract = dataContract;
var defaultValueType = defaultValue?.GetType();

if (defaultValueType != null && defaultValueType != modelType)
{
exampleContract = GetDataContractFor(defaultValueType);
}

var defaultAsJson = exampleContract.JsonConverter(defaultValue);
schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson);
schema.Default = GenerateDefaultValue(dataContract, modelType, defaultValue);
}

schema.ApplyValidationAttributes(customAttributes);
Expand Down Expand Up @@ -544,5 +519,24 @@ private void ApplyFilters(
filter.Apply(schema, filterContext);
}
}

private IOpenApiAny GenerateDefaultValue(
DataContract dataContract,
Type modelType,
object defaultValue)
{
// If the types do not match (e.g. a default which is an integer is specified for a double),
// attempt to coerce the default value to the correct type so that it can be serialized correctly.
// See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2885 and
// https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2904.
var defaultValueType = defaultValue?.GetType();
if (defaultValueType != modelType)
{
dataContract = GetDataContractFor(defaultValueType);
}

var defaultAsJson = dataContract.JsonConverter(defaultValue);
return OpenApiAnyFactory.CreateFromJson(defaultAsJson);
}
}
}

0 comments on commit b10358c

Please sign in to comment.