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

Manually post-process the generated structure?

Open theplankmeister opened this issue 3 years ago • 1 comments

Description I have an API that returns a model that in turn contains another model, but from an external package, and one of the properties on that model is of the type System.Net.HttpStatusCode.

When my model is referenced as the Type in my OpenApiResponseWithBody, it correctly renders the enum in the generated output, but because the HttpStatusCode enum contains multiple definitions of the same status code, (for example, Moved and MovedPermanently both return 301) the array of potential values given in the generated definition contains duplicates.

When the project is deployed to our Azure infrastructure, Azure API Management fails with a ValidationError: Parsing error(s): JSON is valid against no schemas from 'oneOf' error, because it expects an enum type to contain unique values.

To Reproduce Add a property of type System.Net.HttpStatusCode to a model, and reference that model as the Type in a OpenApiResponseWithBody attribute, then hit the appropriate Swagger endpoint, which will probably be http://localhost:7071/api/swagger.json. Find the model in the list of definitions, and observe that the generated list of values contains duplicates.

Versions

  • Microsoft.Azure.WebJobs.Extensions.OpenApi v1.3.0
  • Newtonsoft.Json v13.0.1

Additional context I've spent time trying to find some kind of middleware or event in which I might be able to modify the output, but it doesn't seem like there exists any method of achieving the desired result. For example, here you can see the solution implemented in NSwag.

Is there a solution to my problem that I'm not aware of?

theplankmeister avatar May 02 '22 10:05 theplankmeister

In the end I had to implement this:

    public class OpenApiSchemaAugmentor : IDocumentFilter
    {
        public void Apply(IHttpRequestDataObject request, OpenApiDocument document)
        {
            OpenApiSchema property = document.Components.Schemas["extendedProblemDetails"].Properties["status"];
            List<OpenApiInteger> statuses = property.Enum.Cast<OpenApiInteger>().ToList();
            property.Enum = statuses.DistinctBy(c => c.Value).ToList<IOpenApiAny>();
        }
    }

...which is less than ideal, as it requires the use of hardcoded names. It would be good if the OpenApiDocument instance maintained some kind of context of the properties it contains. If it were possible to test if the type was HttpStatusCode then it wouldn't be neccessary to use hardcoded names.

DistinctBy is from https://github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs

theplankmeister avatar May 02 '22 12:05 theplankmeister