Is there a way to display all enums as their string value in swagger instead of their int value?
I want to be able to submit POST actions and put enums according to
If you are using newtonsof.json then use this
using Newtonsoft.Json.Converters;
[JsonConverter(typeof(StringEnumConverter))]
public enum MyEnum
{
A, B
}
If you are using System.Text.Json.Serialization
using System.Text.Json.Serialization;
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MyEnum
{
A, B
}
ASP NET SOLUTION
In my api docs one enum was still shown as int despite the property being marked with StringEnumConverter
. We couldn't afford using the global setting for all enums mentioned above. Adding this line in SwaggerConfig solved the issue:
c.MapType<ContactInfoType>(() => new Schema { type = "string", @enum = Enum.GetNames(typeof(ContactInfoType))});
in .net core 3.1 & swagger 5.0.0 :
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace WebFramework.Swagger
{
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
var enumValues = schema.Enum.ToArray();
var i = 0;
schema.Enum.Clear();
foreach (var n in Enum.GetNames(context.Type).ToList())
{
schema.Enum.Add(new OpenApiString(n + $" = {((OpenApiPrimitive<int>)enumValues[i]).Value}"));
i++;
}
}
}
}
}
and in Startup.cs :
services.AddSwaggerGen(options =>
{
#region EnumDesc
options.SchemaFilter<EnumSchemaFilter>();
#endregion
});
From the docs:
httpConfiguration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "A title for your API");
c.DescribeAllEnumsAsStrings(); // this will do the trick
});
Also, if you want this behavior only on a particular type and property, use the StringEnumConverter:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
[JsonConverter(typeof(StringEnumConverter))]
public Priority Priority {get; set;}
}
.NET CORE 3.1 and SWAGGER 5
if you need a simple solution to selectively make enums passed as strings:
using System.Text.Json.Serialization;
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MyEnum
{
A, B
}
Note, we use System.Text.Json.Serialization
namespace, not the Newtonsoft.Json
!
I wanted to use rory_za's answer in a .NET Core application, but I had to modify it a bit to make it work. Here is the implementation I came up with for .NET Core.
I also changed it so it doesn't assume the underlying type is int
, and use new lines between the values for easier reading.
/// <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)}";
}
}
Then add this to your ConfigureServices
method in Startup.cs:
c.DocumentFilter<EnumDocumentFilter>();