Search code examples
swaggerswashbuckle.aspnetcore

Swashbuckle and .Net Core Web API – Flatten schema for Optional<T>


I'm using Optional<T> and a Custom Converter to implement PATCH with Text.Json on a resource according to Distinguish between NULL and not present using JSON Merge Patch with NetCore WebApi and System.Text.Json

Let's take this example for the DTO:

public class PatchGroupDTO
    {
        public Optional<string?> Name { get; init; }    
        public Optional<string?> NickName{ get; init; }    
    }

Swagger then shows for the 'Example Value'

{
  "name": {
    "value": "string"
  },
  "nickName": {
    "value": "string"
  }
}

and the 'Schema':

PatchGroupDTO{
   name     StringOptional{...}
   nickName StringOptional{...}
}

How can I achieve that Swagger shows the correct input format of the JSON?

{
  "name": "string",
  "nickName": "string"
}

PatchGroupDTO{
   name     string nullable:true
   nickName string nullable:true
}

Is it possible to generally flatten all Optional<T> types?


Solution

  • to flatten an Optional for a specific instance of T is easy by using MapType and a solution using your Optional-type is:

    services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "Elwis.API", Version = "v1" });
            c.MapType<Optional<Guid?>>(() => new OpenApiSchema { Type = "string", Format = "uuid" });
            c.MapType<Optional<DateTime?>>(() => new OpenApiSchema { Type = "string", Format= "date-time" });
            c.MapType<Optional<string?>>(() => new OpenApiSchema { Type = "string" });
            c.MapType<Optional<bool?>>(() => new OpenApiSchema { Type = "boolean" });
            c.MapType<Optional<int?>>(() => new OpenApiSchema { Type = "integer" });
    
    

    My solution is based on: Change property type as exported by Swagger/Swashbuckle.

    If you use Nullable Types you also have to map the nullable types, as mentioned in the article: Swashbuckle MapType<Type> doesn't work with parameters.

    The general problem "flatten all Optional types" is discussed in this article: How to expose a custom generic type as a string in Swagger schema using Swashbuckle.AspNetCore.

    It seems to be possible by using a custom SchemaFilter, but i never tried it and would recommend to stay by mapping the concrete instances needed in your program.