Недавно я обновил свой API с netcore2.1 до netcore3.1
Я надеялся не просить пользователей API переписать свой клиент.
Таким образом, я ожидаю, что мне нужно swagger. json для обратной совместимости.
В старом swagger. json перечисление будет выглядеть как
Но теперь это выглядит так:
Я использую Swashbuckle.AspNetCore 5.2.1
У меня есть расширение AddSwaggerDocumentation, и оно вызывает
services.AddSwaggerGen(c =>
{
c.EnableAnnotations();
c.ParameterFilter<SwaggerEnumParameterFilter>();
c.SchemaFilter<SwaggerEnumFilter>();
где
public class SwaggerEnumFilter : ISchemaFilter
{
public void Apply(OpenApiSchema model, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
var values = Enum.GetValues(context.Type);
var valuesArr = new OpenApiArray();
foreach (var value in values)
{
var item = new OpenApiObject
{
["name"] = new OpenApiString(Enum.GetName(context.Type, value)),
["value"] = new OpenApiString(value.ToString())
};
valuesArr.Add(item);
}
model.Extensions.Add("x-ms-enum", new OpenApiObject
{
["name"] = new OpenApiString(context.Type.Name),
["modelAsString"] = new OpenApiBoolean(true),
["values"] = valuesArr
});
}
}
}
также у меня есть
public static IApplicationBuilder UseSwaggerDocumentation(this IApplicationBuilder app)
{
var basePath = "/v1";
app.UseSwagger(c =>
{
c.RouteTemplate = "api-docs/{documentName}/swagger.json";
c.SerializeAsV2 = true;
c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
swaggerDoc.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}{basePath}" } };
});
});
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("./v1/swagger.json", "Versioned API v1.0"); //
c.RoutePrefix = "api-docs";
});
return app;
}
и
public class SwaggerEnumParameterFilter : IParameterFilter
{
public void Apply(OpenApiParameter parameter, ParameterFilterContext context)
{
var type = context.ApiParameterDescription.Type;
if (type.IsEnum)
{
var values = Enum.GetValues(type);
var valuesArr = new OpenApiArray();
foreach (var value in values)
{
var item = new OpenApiObject
{
["name"] = new OpenApiString(Enum.GetName(type, value)),
["value"] = new OpenApiString(value.ToString())
};
valuesArr.Add(item);
}
parameter.Extensions.Add("x-ms-enum", new OpenApiObject
{
["name"] = new OpenApiString(type.Name),
["modelAsString"] = new OpenApiBoolean(true),
["values"] = valuesArr
});
}
}
}
и
public static class SwaggerGenOptionsExtensions
{
public static SwaggerGenOptions RegisterEnumSchemas(this SwaggerGenOptions options, Assembly assembly, string enumsNamespace)
{
var enums = from t in assembly.GetTypes()
where t.IsEnum && t.Namespace == enumsNamespace
select t;
foreach (var enumerate in enums)
{
var nullableEnumerate = typeof(Nullable<>).MakeGenericType(enumerate);
MapEnumType(options, enumerate, false);
MapEnumType(options, nullableEnumerate, true);
}
return options;
}
private static void MapEnumType(SwaggerGenOptions options, Type enumerate, bool nullable)
{
var underlyingEnum = nullable ? Nullable.GetUnderlyingType(enumerate) : enumerate;
options.MapType(enumerate, () => new OpenApiSchema
{
Type = "string",
Enum = underlyingEnum.GetEnumNames().Select(name => new OpenApiString(name)).Cast<IOpenApiAny>().ToList(),
Nullable = nullable
});
}
}
[обновление]
Попытка предложения BlueJayke