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

DateOnly in response body

Open grantjames opened this issue 3 years ago • 1 comments

I have an azure function with a trigger decorated with the two attributes required for specifiying the input and output:

[OpenApiParameter(name: "myDate", In = ParameterLocation.Query, Required = true, Type = typeof(DateOnly))]
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(DateOnly))]

In the OpenApi definition that gets generated I get the following

"parameters": [
    {
      "in": "query",
      "name": "myDate",
      "required": true
    }
  ],
  "responses": {
    "200": {
      "schema": {
        "$ref": "#/definitions/dateOnly"
      }
    },

Is it possible for both the parameters and responses section to show that I'm expecting a string with a date format?

I've seen this exact issue mentioned and solved for other swagger implementations (example) but there doesn't seem to be a way of mapping a type for this library.

To Reproduce Steps to reproduce the behavior:

  1. Create a new function app with a HTTP trigger
  2. Add the necessary attributes, including the ones above.
  3. Check the resulting swagger doc.

Expected behavior This isn't a bug since it's expected behaviour. I'd just like to know if there's a way I can override the behaviour like in the URL above?

Thank you.

grantjames avatar Nov 08 '22 14:11 grantjames

I ended up creating a filter for this:

/// <summary>
/// Ensures that the type <see cref="DateOnly"/> is rendered as 'string($date)' in the specification.
/// </summary>
internal class DateOnlyFilter() : IDocumentFilter
{
    public void Apply(IHttpRequestDataObject req, OpenApiDocument document)
    {
        document.Components.Schemas.TryGetValue("dateOnly", out var dateOnlySchema);
        if (dateOnlySchema == null)
        {
            return;
        }

        // NOTE: In principle DateOnly should be inlined since it is a primitive type.
        // However it turns out that inlining schema elements that reference a component
        // type is not trivial and we decided that it was not worth the effort
        dateOnlySchema.Type = "string";
        dateOnlySchema.Format = "date";
        dateOnlySchema.Properties.Clear();
    }
}

You need to add the filter using DI like this:

hostBuilder.ConfigureFunctionsWebApplication(builder =>
{
    // ...
}).ConfigureServices(services =>
{
    services.AddSingleton<IOpenApiConfigurationOptions>(sp =>
    {
        var openApiConfigurationOptions = new OpenApiConfigurationOptions();
        openApiConfigurationOptions.DocumentFilters.Add(new DateOnlyFilter());

acatuttle avatar Jan 16 '25 12:01 acatuttle