Swagger UI Web Api documentation Present enums as strings?
Solution 1
Enable globally
From the docs:
httpConfiguration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "A title for your API");
c.DescribeAllEnumsAsStrings(); // this will do the trick
});
Enum/string conversion on particular property
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;}
}
If you're using Newtonsoft and Swashbuckle v5.0.0 or higher
You'll also need this package:
Swashbuckle.AspNetCore.Newtonsoft
And this in your startup:
services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()
There's docs here: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#systemtextjson-stj-vs-newtonsoft
Solution 2
For ASP.NET Core 3 with the Microsoft JSON library (System.Text.Json)
In Startup.cs/ConfigureServices():
services
.AddControllersWithViews(...) // or AddControllers() in a Web API
.AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
For ASP.NET Core 3 with the Json.NET (Newtonsoft.Json) library
Install the Swashbuckle.AspNetCore.Newtonsoft
package.
In Startup.cs/ConfigureServices():
services
.AddControllersWithViews(...)
.AddNewtonsoftJson(options =>
options.SerializerSettings.Converters.Add(new StringEnumConverter()));
// order is vital, this *must* be called *after* AddNewtonsoftJson()
services.AddSwaggerGenNewtonsoftSupport();
For ASP.NET Core 2
In Startup.cs/ConfigureServices():
services
.AddMvc(...)
.AddJsonOptions(options =>
options.SerializerSettings.Converters.Add(new StringEnumConverter()));
Pre-ASP.NET Core
httpConfiguration
.EnableSwagger(c =>
{
c.DescribeAllEnumsAsStrings();
});
Solution 3
So I think I have a similar problem. I'm looking for swagger to generate enums along with the int -> string mapping. The API must accept the int. The swagger-ui matters less, what I really want is code generation with a "real" enum on the other side (android apps using retrofit in this case).
So from my research this ultimately seems to be a limit of the OpenAPI specification which Swagger uses. It's not possible to specify names and numbers for enums.
The best issue I've found to follow is https://github.com/OAI/OpenAPI-Specification/issues/681 which looks like a "maybe soon" but then Swagger would have to be updated, and in my case Swashbuckle as well.
For now my workaround has been to implement a document filter that looks for enums and populates the relevant description with the contents of the enum.
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 = property.@enum;
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 = param.@enum;
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());
}
}
This results in something like the following on your swagger-ui so at least you can "see what you're doing":
Solution 4
ASP.NET Core 3.1
To generate enums as strings using Newtonsoft JSON you must explicitly add Newtonsoft support by adding AddSwaggerGenNewtonsoftSupport()
as follows:
services.AddMvc()
...
.AddNewtonsoftJson(opts =>
{
opts.SerializerSettings.Converters.Add(new StringEnumConverter());
});
services.AddSwaggerGen(...);
services.AddSwaggerGenNewtonsoftSupport(); //
This is available via a new package, Swashbuckle.AspNetCore.Newtonsoft
. It looks like everything else works fine without this package apart from enum converter support.
Solution 5
.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
!
Related videos on Youtube
Admin
Updated on April 29, 2022Comments
-
Admin almost 2 years
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 their string value without having to look at the enum every time.
I tried
DescribeAllEnumsAsStrings
but the server then receives strings instead of the enum value which is not what we're looking for.Has anyone solved this?
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 }
-
Hux almost 8 yearsDo you want the schema to describe the value as a string but then post an integer to the server? JSON.net will handle both values fine, so is the integer only version a definite requirement? I don't think Swagger supports a enum type with both the string and integer value.
-
Federico Dipuma almost 8 yearsYour expected behavior is unclear, can you better explain what you want Swagger UI to display and what you want to POST/PUT to your Web API with examples?
-
Admin almost 8 yearsMoreover, if I have GET methods that take enum in the url, I want the scheme to describe it as strings in the drop down list of suggested values
-
Hux almost 8 yearsWhy does integer validation fail? The type should be an enum in the model and the json media formatter would correctly handle either a string or int. If you update the question with an example it would help us understand why the validation is failing.
-
Admin almost 8 yearsI added code example, hope it will be clear
-
Triynko about 6 yearsIf it's a flags enum, the it has to be numeric, unless you have enum values defined for every possible combination of flags. It's nuts that swagger doesn't display BOTH the name and value for each enum, and instead displays number alone (useless) or names alone (again, useless for flags which must be specified as numbers).
-
-
Lineker over 6 yearsthis doesn't work for me.[EnumDataType(typeof(Priority))] [JsonConverter(typeof(StringEnumConverter))]
-
Lineker over 6 years@NH. yes, i used newtonsoft.json
-
NH. over 6 years@Lineker, post your error as a new question, following this guide: stackoverflow.com/help/mcve
-
NSGaga-mostly-inactive over 6 years+1 I was looking to add descriptions to enums (just to 'describe enum'), never thought of this. I already have misc filters in place, but was looking for something more 'organic', but there's no support. Well then, filters all the way :)
-
aruno about 6 yearsThx! I think I might just leave your comment in the source too #thiswilldothetrick
-
aruno about 6 yearsHmm why is EnumDataType required? Is there a way to make it smart enough to auto detect
-
Xavero about 6 yearsif you use the line with "#thiswilldothetrick", you dont need the StringEnumConverterAttribute. The Attibutes are only required when you want this feature in a specific Property. Also, I dont remember what the EnumDataTypeAttribute does, but perphaps you dont need it.
-
Gabriel Luci almost 6 yearsThanks! I used this in my project, but modified it to work with .NET Core. I added my implementation as an answer.
-
Softlion over 5 yearsPossible to remove the Enum: Array [ 6 ] which appears below ?
-
spottedmahn over 5 yearsASP.NET Core documentation: Customize Schema for Enum Types
-
Jerico Sandhorn over 5 yearsworked instantly for me. How do I make them lower case now?
-
Xavero over 5 yearsI think the Lowercase its achieved with the Json converter/Newtonsoft, but i am not sure.
-
Xavero over 5 yearsOh, nevermind, sppotedmahn's link shows how to do it: c.DescribeStringEnumsInCamelCase();
-
bugged87 over 5 years
DescribeAllEnumsAsStrings
worked for object properties and even query parameters on controller actions. However, usingEnumDataTypeAttribute
andJsonConverter(typeof(StringEnumConverter))
did not work for me. -
Rabban over 5 yearsGreat solution, but the extensions in
DescribeEnumParameters
were empty in my project. I had to cast theparam
toNonBodyParameter
and check the enum there:if (param is NonBodyParameter nbParam && nbParam.Enum?.Any() == true) { param.Description += DescribeEnum(nbParam.Enum); }
-
Carlos Beppler about 5 yearsOn my project Extensions is empty too, used the @Rabban solution.
-
Gabriel Luci almost 5 years@Rabban I updated my code to include that. Can you just verify I put it in the right place? I didn't have this issue. Maybe a newer version changed things.
-
Rabban almost 5 years@GabrielLuci Confirmed and approved ;)
-
Bashir Momen over 4 yearsIt is using Newtonsoft instead of new asp.net core JSON serialization.
-
Bernard Vander Beken over 4 yearsHey @Bashir, is there a swachbuckle issue to keep track of the lack of that support?
-
Bashir Momen over 4 yearsHi @bernard-vander-beken, I did not report that but I assume there is. It is good if we can find it and add it to this post for a later updates.
-
Bashir Momen over 4 yearsThis option is deprecated in the Swashbuckle. It is recommended to use the ASP.NET Core option and then Swashbuckle can reflect that.
-
Node.JS over 4 years
DescribeAllEnumsAsStrings
is deprecated -
jeremyh over 4 yearsLooks like its here: github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1269
-
Guillaume over 4 yearsProblem of using options.SerializerSettings.Converters.Add(new StringEnumConverter())) is that your changing the json for all your methods, not only for Sawshbuckle.
-
Rocklan over 4 yearsSolution works great, thanks so much. Any reason why DescribeEnumParameters is static?
-
Gabriel Luci over 4 years@Rocklan Because it can be :) And static methods are slightly more efficient than ones that aren't.
-
A. Tretiakov about 4 yearsThis solution omits important step of registering StringEnumConverter as a converter in AddNewtonsoftJson section of AddMvc. See example in @Roman Starkov answer below.
-
A. Tretiakov about 4 yearsIt helps to setup this convention globally, but if you need to apply this only to certain types of enums, you will need to carefully read this issue. TL; DR: It's not possible to apply new StringEnumConverter() to property only, but you can apply it to the whole enum type.
-
Roman Starkov about 4 yearsI suppose if we're talking of gotchas, it's also not possible to use a completely custom converter. Swagger doesn't run the enum values through the custom converter; it simply recognizes
StringEnumConverter
as a special case. -
user2864740 about 4 years
GetMembers()
would be better asGetMembers(BindingFlags.Static | BindingFlags.Public)
to limit to only the actual declared enum properties such as "Blue". I also adapted the "else" case to return the Member.Name if there is no[EnumMember]
attribute. -
Matyas almost 4 yearsDown side of this is, that when executing a request, instead of passing only int representation (like 2 for example) of an enum value the API will get the full description as a value (like LogicError = 3), which will fail as a bad request since it is not valid value for the enum.
-
Matyas almost 4 yearsThis only works when the parameter type is exactly enum... not nullable enum, collection of enums etc. Check my answer for those cases.
-
Dan Friedman almost 4 yearsDoes anyone have a solution for Azure Functions v2 and/or v3?
-
lsuarez almost 4 yearsYou should also ensure that you update the
model.Format
to"string"
as it will generally be"int32"
. -
MovGP0 almost 4 yearsThis one works showing the proper values, and also works when converting the values back to the enum. Note that you need to add the NuGet package
System.Text.Json
. -
Nilay Mehta almost 4 yearsThat's what I was looking for! As I have to use string for just single enum, and
DescribeAllEnumsAsStrings
will convert all enums to the string. -
Ian Kemp over 3 years@DanFriedman Considering Swashbuckle doesn't work with Azure Functions at all, you're out of luck.
-
wolfyuk over 3 years@IanKemp There is third party support with the
AzureExtensions.Swashbuckle
package but like @DanFriedman I cannot get the enum-to-string working as expected -
Kirsten over 3 yearsWhen I run this code I find that enumOption is of type OpenApiString in DescribeEnum
-
Mahesh over 3 yearsThanks for this simple solution. I'm using .NET Core 3.1 and Swagger 5.5. didn't need to use DescribeAllEnumsAsStrings . Just set [JsonConverter(typeof(JsonStringEnumConverter))] on enum. EX: System.Text.Json.Serialization; [JsonConverter(typeof(JsonStringEnumConverter))] public enum Category { Autos, Electronics, Furniture, House, Pets, Miscellaneous }
-
Andy Vaal over 3 yearsIf you're configuring for ASP.NET Core 3 with Newtonsoft, the
AddSwaggerGenNewtonsoftSupport()
extension method is available from NuGet packageSwashbuckle.AspNetCore.Newtonsoft
. Read more here: github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/… -
Yaroslav Bres over 3 yearsYour solution is working, only if I change
GetEnumTypeByName
FirstOfDefaultCondition to this.FirstOrDefault(x => x.FullName == enumTypeName || x.Name == enumTypeName);
-
fingers10 over 3 yearsThis worked for me. If you are using Newtonsoft Json in your asp.net core project. The you need to explicitly this. Thanks @user30844147
-
developer learn999 over 3 yearsthis works only on Core3.0, filter not exist in Core2
-
developer learn999 over 3 yearsin core2.0 it displays the keys, but not the values as expected. also data member description not works see stackoverflow.com/questions/64764537/…
-
developer learn999 over 3 yearswhat value should i put above each value? currently i get error : - $exception {"Type provided must be an Enum.\r\nParameter name: enumType"} System.ArgumentException
-
computercarguy over 3 years
c.DescribeAllEnumsAsStrings();
is deprecated in Swagger 5.6.0. -
Cubicle.Jockey over 3 yearsA very important step.
-
ehsan rezaee about 3 yearsApiResult is a response class . validation of enum in imput parameter is another discuese in .core you can use IValidatableObject and implementation : public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) on object
-
sasi reka about 3 yearsIt works in .Net 5. DescribeAllEnumsAsStrings (deprecated) and AddSwaggerGenNewtonsoftSupport is not working in .Net 5.
-
Askolein about 3 yearsIn .NET core 5, the
.Converters.Add(..)
approach does not work for me, while the[JsonConverter(typeof(StringEnumConverter))]
without having any other settings. Any idea why? -
Azimuth almost 3 years
AddNewtonsoftJson
acceptsIMvcBuilder
. It won't work withIServiceCollection
. Please fix your code for For ASP.NET Core 3 with the Json.NET (Newtonsoft.Json) library. -
manymanymore almost 3 yearsWhere can I get the
httpConfiguration
object? -
Maulik Modi almost 3 yearsWhat is the recommended solution in .net 5?
-
Maulik Modi almost 3 yearsIs there any global option instead of decorating POCOs with Json converter attributes? How does it appear in swagger doc? Does it generate Enum on the client side code generation as well?
-
TK-421 almost 3 yearsI had to update the model.Type to "string" for the same reason Isuarez mentioned.
-
HenryMigo almost 3 yearsOnly thing that worked for me for what I wanted.
-
Nicholas Petersen over 2 yearsBravo. While I am forced to continue using Newtonsoft.Json, I didn't necessarily need that to be recognized in the API documentation generation, I just needed enums to be represented as strings. Barring a more complicated scenario (like custom newtonsoft enum names), surprisingly this just worked.
-
sergeyxzc over 2 yearsThanks! This is what helped me in my net5 project
-
vahid over 2 years@MaulikModi In Swagger doc, it changes the type to string and provides a list of available values.
-
Amir Chatrbahr over 2 yearsfew tweaks to make it work: 1-
model.Format = null;
2-model.Type = "string";
-
Ulterior over 2 yearsThis was actually what worked with NSwagStudio export
-
Rich Hopkins about 2 yearsI spent three days looking for this. Tried stuff that involved other libraries, but didn't give me what I needed. Here you go showing me how to do it in 4 lines of code. Thanks!
-
John Demetriou about 2 yearsThis doesn't exist. Any alternatives?
-
OhWelp about 2 yearsThis will render your swagger requests unusable as it will overwrite your int representation of value. Use with caution.
-
ping over 1 yearThank you, this works fine and is exactly what i was looking for. But it rises a new issue. The example JSON value of the request in the Swagger UI, shows the required enum as defined in the EnumSchemaFilter which results in: { ...."language": "en(1)",...}. The "Try it out" and then 'execute' button won't work whit this adaption. Any improvement advises for this issue?
-
Kiquenet over 1 yearand for NET 6 minimal API ?