Swashbuckle.WebApi
Swashbuckle.WebApi copied to clipboard
x-enumNames
VERSION:
Swashbuckle.AspNetCore -Version 3.0.0
STEPS TO REPRODUCE:
public enum Currency
{
Unknown = 0,
Usd,
Euro,
}
EXPECTED RESULT:
"currency": {
"format": "int32",
"enum": [
0,
1,
2
],
"type": "integer",
"x-enumNames": [
"Unknown",
"Usd",
"Euro"
]
}
ACTUAL RESULT:
"currency": {
"format": "int32",
"enum": [
0,
1,
2
],
"type": "integer"
}
ADDITIONAL DETAILS
Please add x-enumNames attribute It is very useful for NSwag integration and auto-generating client code (see https://github.com/RSuter/NSwag/issues/1234 and https://stackoverflow.com/questions/36452468/swagger-ui-web-api-documentation-present-enums-as-strings)
It can be like
public class SwaggerAddEnumDescriptions : IDocumentFilter
{
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);
property.Extensions.Add("x-enumNames", GetStringMapping(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 string[] GetStringMapping(IList<object> enums)
{
var enumDescriptions = new List<string>();
Type type = null;
foreach (var enumOption in enums)
{
if (type == null) type = enumOption.GetType();
enumDescriptions.Add(Enum.GetName(type, enumOption));
}
return enumDescriptions.ToArray();
}
private static void DescribeEnumParameters(IList<IParameter> parameters)
{
if (parameters == null) return;
foreach (var param in parameters)
{
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)}";
}
}
and usage
options.DocumentFilter<SwaggerAddEnumDescriptions>();
//options.DescribeAllEnumsAsStrings();
Currently you can do it as easy as:
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
var array = new OpenApiArray();
array.AddRange(Enum.GetNames(context.Type).Select(n => new OpenApiString(n)));
schema.Extensions.Add("x-enumNames", array);
}
}
}
And when configuring:
options.SchemaFilter<EnumSchemaFilter>();
When we are using NSwag, I guess we are all using the excellent implementation of EnumSchemaFilter described by @sherlock1982 above.
On our side, we need to keep the enum: [10, 20, 30] as integer, it's important for typescript NSwag generation the enumerables were correctly formatted (something like Wire = 10, Bluetooth = 20, Wifi = 30).
swagger.json
NSwag generation
But on the UI interface, the generation does not display the x-enumNames, so we only see AccessoryConnectionEnum: [ 10, 20, 30 ]
It's a lack of information, our partners asked us the meaning of these values, we need to maintain a documentation for enums, it makes no sense because the enums values are listed inside the swagger.json, but not displayed on the UI side...
Could it be part of the roadmap ?
I have seen the same discussion on other stack with swagger implementation. https://github.com/swagger-api/swagger-ui/pull/6948#issuecomment-780935833
I agree with that, would be nice to have additional description for those x-enumNames