Документация Swagger UI Web Api Представляем перечисления как строки?
Есть ли способ показать все перечисления как их строковое значение в swagger вместо их значения int?
Я хочу, чтобы иметь возможность отправлять POST-действия и помещать перечисления в соответствии со своим строковым значением, не просматривая каждый раз перечисление.
Я попробовал DescribeAllEnumsAsStrings
, но затем сервер получает строки вместо значения перечисления, которое не то, что мы ищем.
Кто-нибудь решил это?
Edit:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
public Priority Priority {get; set;}
}
public class LettersController : ApiController
{
[HttpPost]
public IHttpActionResult SendLetter(Letter letter)
{
// Validation not passing when using DescribeEnumsAsStrings
if (!ModelState.IsValid)
return BadRequest("Not valid")
..
}
// In the documentation for this request I want to see the string values of the enum before submitting: Low, Medium, High. Instead of 0, 1, 2
[HttpGet]
public IHttpActionResult GetByPriority (Priority priority)
{
}
}
public enum Priority
{
Low,
Medium,
High
}
Ответы
Ответ 1
Из документов:
httpConfiguration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "A title for your API");
c.DescribeAllEnumsAsStrings(); // this will do the trick
});
Кроме того, если вы хотите, чтобы это поведение выполнялось только для определенного типа и свойства, используйте StringEnumConverter:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
[JsonConverter(typeof(StringEnumConverter))]
public Priority Priority {get; set;}
}
Ответ 2
Поэтому я думаю, что у меня похожая проблема. Я ищу swagger для генерации перечислений вместе с int → string mapping. API должен принять int. Swagger-ui менее важен, я действительно хочу генерацию кода с "реальным" перечислением на другой стороне (в этом случае приложения для Android используют модификацию).
Так что из моих исследований это в конечном счете кажется ограничением спецификации OpenAPI, которую использует Swagger. Невозможно указать имена и номера для перечислений.
Лучшая проблема, за которой я обнаружил, - https://github.com/OAI/OpenAPI-Specification/issues/681, которая выглядит как "возможно, скоро", но тогда Swagger придется обновить, а в моем случае Swashbuckle как Что ж.
На данный момент мой обходной путь заключается в реализации фильтра документов, который ищет перечисления и заполняет соответствующее описание содержимым перечисления.
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.DocumentFilter<SwaggerAddEnumDescriptions>();
//disable this
//c.DescribeAllEnumsAsStrings()
SwaggerAddEnumDescriptions.cs:
using System;
using System.Web.Http.Description;
using Swashbuckle.Swagger;
using System.Collections.Generic;
public class SwaggerAddEnumDescriptions : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
// add enum descriptions to result models
foreach (KeyValuePair<string, Schema> schemaDictionaryItem in swaggerDoc.definitions)
{
Schema schema = schemaDictionaryItem.Value;
foreach (KeyValuePair<string, Schema> propertyDictionaryItem in schema.properties)
{
Schema property = propertyDictionaryItem.Value;
IList<object> propertyEnums = [email protected];
if (propertyEnums != null && propertyEnums.Count > 0)
{
property.description += DescribeEnum(propertyEnums);
}
}
}
// add enum descriptions to input parameters
if (swaggerDoc.paths.Count > 0)
{
foreach (PathItem pathItem in swaggerDoc.paths.Values)
{
DescribeEnumParameters(pathItem.parameters);
// head, patch, options, delete left out
List<Operation> possibleParameterisedOperations = new List<Operation> { pathItem.get, pathItem.post, pathItem.put };
possibleParameterisedOperations.FindAll(x => x != null).ForEach(x => DescribeEnumParameters(x.parameters));
}
}
}
private void DescribeEnumParameters(IList<Parameter> parameters)
{
if (parameters != null)
{
foreach (Parameter param in parameters)
{
IList<object> paramEnums = [email protected];
if (paramEnums != null && paramEnums.Count > 0)
{
param.description += DescribeEnum(paramEnums);
}
}
}
}
private string DescribeEnum(IList<object> enums)
{
List<string> enumDescriptions = new List<string>();
foreach (object enumOption in enums)
{
enumDescriptions.Add(string.Format("{0} = {1}", (int)enumOption, Enum.GetName(enumOption.GetType(), enumOption)));
}
return string.Join(", ", enumDescriptions.ToArray());
}
}
Это приводит к чему-то вроде следующего на вашем swagger-интерфейсе, так что вы, по крайней мере, можете "увидеть, что вы делаете": ![enter image description here]()
Ответ 3
Я хотел использовать ответ rory_za в приложении .NET Core, но мне пришлось немного его изменить, чтобы он работал. Вот реализация, которую я придумал для .NET Core.
Я также изменил его, чтобы он не предполагал, что основным типом является int
, и использую новые строки между значениями для облегчения чтения.
/// <summary>
/// Add enum value descriptions to Swagger
/// </summary>
public class EnumDocumentFilter : IDocumentFilter {
/// <inheritdoc />
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) {
// add enum descriptions to result models
foreach (var schemaDictionaryItem in swaggerDoc.Definitions) {
var schema = schemaDictionaryItem.Value;
foreach (var propertyDictionaryItem in schema.Properties) {
var property = propertyDictionaryItem.Value;
var propertyEnums = property.Enum;
if (propertyEnums != null && propertyEnums.Count > 0) {
property.Description += DescribeEnum(propertyEnums);
}
}
}
if (swaggerDoc.Paths.Count <= 0) return;
// add enum descriptions to input parameters
foreach (var pathItem in swaggerDoc.Paths.Values) {
DescribeEnumParameters(pathItem.Parameters);
// head, patch, options, delete left out
var possibleParameterisedOperations = new List<Operation> {pathItem.Get, pathItem.Post, pathItem.Put};
possibleParameterisedOperations.FindAll(x => x != null)
.ForEach(x => DescribeEnumParameters(x.Parameters));
}
}
private static void DescribeEnumParameters(IList<IParameter> parameters) {
if (parameters == null) return;
foreach (var param in parameters) {
if (param is NonBodyParameter nbParam && nbParam.Enum?.Any() == true) {
param.Description += DescribeEnum(nbParam.Enum);
} else if (param.Extensions.ContainsKey("enum") && param.Extensions["enum"] is IList<object> paramEnums &&
paramEnums.Count > 0) {
param.Description += DescribeEnum(paramEnums);
}
}
}
private static string DescribeEnum(IEnumerable<object> enums) {
var enumDescriptions = new List<string>();
Type type = null;
foreach (var enumOption in enums) {
if (type == null) type = enumOption.GetType();
enumDescriptions.Add($"{Convert.ChangeType(enumOption, type.GetEnumUnderlyingType())} = {Enum.GetName(type, enumOption)}");
}
return $"{Environment.NewLine}{string.Join(Environment.NewLine, enumDescriptions)}";
}
}
Затем добавьте это в ваш метод ConfigureServices
в Startup.cs:
c.DocumentFilter<EnumDocumentFilter>();
Ответ 4
Для ASP.Net Core просто сделайте это в Startup.cs/ConfigureServices():
services
.AddMvc(...)
.AddJsonOptions(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()));
Подход DescribeAllEnumsAsStrings()
, который все остальные, похоже, дают, не работает для меня, потому что тогда, как сказал OP, сервер получает строки и ожидает целочисленные значения. Чтобы сервер мог ожидать строки, вам нужно добавить StringEnumConverter в SerializerSettings, как описано выше, плюс вы можете полностью исключить DescribeAllEnumsAsStrings().
Ответ 5
Я только что сделал это, и он отлично работает!
Startup.cs
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
Model.cs
public enum ColumnType {
DATE = 0
}
swagger.json
type: {
enum: ["DATE"],
type: "string"
}
Я надеюсь, что это поможет вам, как это помогло мне!
Ответ 6
написать код внутри Startup.cs
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
Ответ 7
.Net Core 3.0
using Newtonsoft.Json.Converters;
services
.AddMvc(options =>
{
options.EnableEndpointRouting = false;
})
.AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()))
Ответ 8
С ядром asp.net 3
using System.Text.Json.Serialization;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
Но похоже, что версия Swashbuckle 5.0.0-rc4 не готова это поддерживать. Поэтому нам нужно использовать параметр (не рекомендуется) в конфигурационном файле Swashbuckle, пока он не будет поддерживать и отображать его как библиотеку Newtonsoft.
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.DescribeAllEnumsAsStrings();
Разница между этим ответом и другими ответами заключается в использовании только библиотеки Microsoft JSON вместо Newtonsoft.