В нашем веб-API ASP.net Core наши DTO имеют строковые свойства, допустимые значения которых определены в перечислениях. (Мы планируем изменить тип этих свойств на соответствующие перечисления, но пока это невозможно.)
В интересах наших потребителей API мы хотели бы, чтобы пользовательский интерфейс Swagger (Swashbuckle.AspNetCore) показывал возможные значения этих перечислений. Могу ли я настроить Swagger так, чтобы эти значения перечисления отображались в схеме (отдельно или в соответствующей схеме DTO) без изменения типа свойств?
public class FooDTO
{
public int Id {get; set;}
public string Color {get; set;} // Only has values of FooColor
// ...
}
public enum FooColor
{
Purple,
Blue,
Pink
}
Я бы хотел, чтобы значения FooColor
отображались в схеме пользовательского интерфейса Swagger или вообще где угодно.
Мне помогла реализация следующего ISchemaFilter
. Примечание: мой Json сериализует CamelCasing. Вот почему я добавил formattedPropertyName
, приспосабливайтесь к вашим потребностям.
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
// Check if the property is of type string and has a corresponding enum
foreach (var property in context.Type.GetProperties().Where(p => p.PropertyType == typeof(string)))
{
var matchedConfig = GetEnumTypeAndName.FirstOrDefault(x => x.specifiedClass == context.Type
&& x.specifiedPropertyName == property.Name);
if (matchedConfig == default)
continue;
// Get the enum type for the property
Type enumType = matchedConfig.enumType;
string formattedPropertyName = System.Text.Json.JsonNamingPolicy.CamelCase.ConvertName(property.Name);
// Get the enum values and add them to the schema
var enumValues = Enum.GetNames(enumType)
.Select(name => new OpenApiString(name))
.ToList<IOpenApiAny>();
schema.Properties[formattedPropertyName].Enum = enumValues;
}
}
private static List<(Type specifiedClass, string specifiedPropertyName, Type enumType)> GetEnumTypeAndName
{
get
{
{
return new List<(Type, string, Type)>() {
(typeof(FooDTO), nameof(FooDTO.Color), typeof(FooColor))
};
}
}
}
}
И затем в Program.cs
или Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
// Register the custom schema filter
c.SchemaFilter<EnumSchemaFilter>();
});
}