azure-functions-openapi-extension icon indicating copy to clipboard operation
azure-functions-openapi-extension copied to clipboard

Is it possible to add documentation to enums?

Open MartinWickman opened this issue 2 years ago • 1 comments

Describe the issue

When your endpoint returns a model containing an enum, there is no way (that I know of) to add a descriptive text to each possible enum value. The [OpenApiProperty] attribute doesn't work on enums. Maybe this is not possible in C# for technical reasons, but there is support for it in the swagger spec afaik

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum Status
{
    [OpenApiProperty(Description = "This invoice is paid")]  // <-- does not work.
    Paid,
    Unpaid,
}

MartinWickman avatar Jun 02 '22 09:06 MartinWickman

The OAS spec does not allow for descriptions on individual enum values (ref https://swagger.io/specification/#server-variable-object , enum is a string array only).

One solution would be to allow the OpenApiProperty attribute on enum members (as well as enum definitions and class definitions). Another option is to read the System.ComponentModel.DescriptionAttribute for enum members (and enum definition and class definitions). My code already has enums documented using [Description("info")].

For example:

[Description("Defines invoice statuses")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum InvoiceStatus
{
    [Description("This invoice is paid")]
    Paid,
    [Description("This invoice is not yet paid")]
    Unpaid,
}

public static string GetEnumTypeDescription(Type type)
        {
            
            var descriptions = type.GetCustomAttributes(false).OfType<DescriptionAttribute>().Select(d => d.Description).ToList();
            foreach (var enumValue in type.GetEnumValues())
            {
                descriptions.AddRange(type.GetMember(enumValue.ToString()).SelectMany(t => t.GetCustomAttributes(false)).OfType<DescriptionAttribute>().Select(d => $"{enumValue}: {d.Description}"));
            }
            if (descriptions.Any())
            {
                return string.Join("\n", descriptions);
            }
            return null;
                
        }

Resullt:

Defines invoice statuses
Paid: This invoice is paid
Unpaid: This invoice is not yet paid

The json would then be:

"InvoiceStatus": {
            "enum": [
              "Paid",
              "Unpaid"            ],
            "type": "string",
            "description": "Defines invoice statuses\nPaid: This invoice is paid\nUnpaid: This invoice is not yet paid",
            "default": "Paid"
          }

rockgecko-development avatar Jun 16 '22 07:06 rockgecko-development