'How to serialize enum as string in Function App running on .net5 with OpenAPI/Swagger?
I am exploring Function App running on .net5 in the new isolated mode. I have HTTP triggered functions that I want to advertise via OpenAPI / Swagger.
To do so, I am using the package Microsoft.Azure.WebJobs.Extensions.OpenApi in preview (0.7.2) to add the OpenAPI functionality to my Function App.
I am trying to have the enums to be shown as string in the OpenAPI page but I can't have it working properly.
Here is the setup in the Program.cs file:
    public static class Program
    {
        private static Task Main(string[] args)
        {
            IHost host = new HostBuilder()
                .ConfigureAppConfiguration(configurationBuilder =>
                {
                    configurationBuilder.AddCommandLine(args);
                })
                .ConfigureFunctionsWorkerDefaults(builder =>
                {
                    builder.Services.Configure<JsonSerializerOptions>(options =>
                    {
                        options.Converters.Add(new JsonStringEnumConverter());
                        options.PropertyNameCaseInsensitive = true;
                    });
                })
                .ConfigureServices(services =>
                {
                    //  Registers any services.             
                })
                .Build();
            return host.RunAsync();
        }
    }
Here is the enum:
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public enum ApprovalContract
    {
        [EnumMember(Value = "Approved")]
        Approved = 1,
        [EnumMember(Value = "Rejected")]
        Rejected = 2
    }
And one of the class that uses it:
    public sealed class DeletionResponseContract
    {
        [JsonPropertyName("approval")]
        public ApprovalContract Approval { get; set; }
    }
I replaced any references to Newtonsoft.Json by System.Text.Json everywhere.
Here is the output in the Swagger page:
Question
How can I serialize enum as string instead of int in the Swagger page with an HTTP triggered Azure Function running on .net5?
Update
I saw that the JsonStringEnumConverter's constructor gives the indication to allow integer values:
     public JsonStringEnumConverter(JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true)
    {
      this._namingPolicy = namingPolicy;
      this._converterOptions = allowIntegerValues ? EnumConverterOptions.AllowStrings | EnumConverterOptions.AllowNumbers : EnumConverterOptions.AllowStrings;
    }
I modified my configuration like this, without any success:
builder.Services.Configure<JsonSerializerOptions>(options =>
{
     options.Converters.Add(new JsonStringEnumConverter(allowIntegerValues: false));
     options.PropertyNameCaseInsensitive = true;
});
							
						Solution 1:[1]
You must implemente ISchemaFilter and set it on AddSwaggerGen. It will generate a better description of your enum items.
builder.Services.AddSwaggerGen(c =>
{
    c.SchemaFilter<EnumSchemaFilter>();
});
//your implementation
public class EnumSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema model, SchemaFilterContext context)
        {
            if (context.Type.IsEnum)
            {
                model.Enum.Clear();
                Enum.GetNames(context.Type)
                    .ToList()
                    .ForEach(name => model.Enum.Add(new OpenApiString($"{Convert.ToInt64(Enum.Parse(context.Type, name))} - {name}")));
            }
        }
    }
    					Solution 2:[2]
I was inspired by Murilo's answer, but couldn't get it to work. So here is an alternative solution:
Create a document filter that will:
find all the enum properties in you swagger schemas
then find the matching property in your code using reflection (note: this doesn't take account of namespaces, so if you have multiple classes with the same name it could fail)
update the swagger property with the values from the c# enum
public class EnumDocumentFilter : IDocumentFilter { public void Apply(IHttpRequestDataObject req, OpenApiDocument document) { foreach(var schema in document.Components.Schemas) foreach(var property in schema.Value.Properties) if (property.Value.Enum.Any()) { var schemaType = Assembly.GetExecutingAssembly().GetTypes().Single(t => t.Name == Camel(schema.Key)); var propertyType = schemaType.GetProperty(Camel(property.Key)).PropertyType; property.Value.Enum = Enum.GetNames(propertyType) .Select(name => new OpenApiString(name)) .Cast<IOpenApiAny>() .ToList(); property.Value.Type = "string"; property.Value.Default = property.Value.Enum.First(); property.Value.Format = null; } } private static string Camel(string key) => $"{char.ToUpperInvariant(key[0])}{key[1..]}"; }
Then register that filter in your OpenApiConfigurationOptions
    public class OpenApiConfigurationOptions : DefaultOpenApiConfigurationOptions
    {
...
        public override List<IDocumentFilter> DocumentFilters { get => base.DocumentFilters.Append(new EnumDocumentFilter()).ToList(); }
    }
    					Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Murilo Maciel Curti | 
| Solution 2 | Alan Hinton | 

