7

I have a class that is exposed through Swashbuckle that looks something like this:

public class Person
{
     [JsonProperty("dateOfBirth")]
     [JsonConverter(typeof(DateFormatConverter))]
     public System.DateTime? DateOfBirth { get; set; }
}

internal class DateFormatConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter
{
    public DateFormatConverter()
    {
        DateTimeFormat = "yyyy-MM-dd";
    }
}

(The class was generated by NSwag-studio)

When I use app.UseSwagger(); to generate a Swagger contract with Swashbuckle, the result looks like this:

"Person": {
    "dateOfBirth": {
      "format": "date-time",
      "type": "string"
    }
  }
}

I would like to configure Swashbuckle to recognize my DateFormatConverter class and treat the format accordingly.

I tried options.SchemaFilter<DateFormatSchemaFilter>() in my Startup class, but the filter doesn't have the context of the property, so unless I want all DateTime objects to be date, this isn't a viable option.

Johannes Brodwall
  • 7,673
  • 5
  • 34
  • 28

1 Answers1

9

Here is how you can change the "date-time" to "date" with an iDocumentFilter:

private class Flip2DateDocumentFilter : IDocumentFilter
{
    private List<string> DateTypes(Type AttribType)
    {
        var list = new List<string>();
        foreach (var p in AttribType.GetProperties())
            if (p.CustomAttributes?.Count() > 0)
                list.Add(p.Name);
        return list;
    }

    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry s, IApiExplorer a)
    {
        var t = typeof(Person);
        if (swaggerDoc.definitions[t.Name] != null)
        {
            var dates = DateTypes(t);
            if (dates.Count() > 0)
                foreach (var p in swaggerDoc.definitions[t.Name].properties)
                    if (dates.Contains(p.Key) && p.Value.format == "date-time")
                        p.Value.format = "date";
        }
    }
}

The key in that code is the var t = typeof(Person); that is the class that will be crawled looking for dates with CustomAttributes.

And of course this code code is not meant for copy/pasting just a small example of what you can do with IDocumentFilter


Another option will be to use [NodaTime][1] and then use `NodaTime.LocalDate` to those properties that should be just dates, and in your swagger config use the MapType

c.MapType<NodaTime.LocalDate>(() => new Schema { type = "string", format = "date" });


I have both of those options working on this example:
http://swagger-net-test.azurewebsites.net/swagger/ui/index?filter=Date#/Date/Date_Post

And the code behind that is on github:
https://github.com/heldersepu/Swagger-Net-Test/blob/master/Swagger_Test/App_Start/SwaggerConfig.cs

Helder Sepulveda
  • 15,500
  • 4
  • 29
  • 56
  • Super answer! I was not aware of the `IDocumentFilter`, which perfectly matches my need. And NodaTime may be a long term goal as well. I ended up making a more generic solution by iterating over `foreach (var typeDef in swaggerDoc.Definitions) { foreach (var property in Type.GetType(namespace + "." + typeDef.Key)` and then checking `JsonPropertyAttribute` for the Swagger property name and `JsonConverterAttribute` for the format. – Johannes Brodwall May 15 '18 at 14:18
  • 1
    Glad I could help, and yes my example was not generic, just to point you on the right direction... – Helder Sepulveda May 15 '18 at 14:22
  • the `c.MapType(...)` doesn't seem to apply to controller method parameters? my swagger doc still shows "date-time" for a parameter defined as LocalDate – Nicholas Franceschina May 10 '19 at 22:56
  • @NickFranceschina Do you have a sample project? Maybe you can post some sample code on a separate question – Helder Sepulveda May 11 '19 at 00:42
  • 1
    @HelderSepulveda - I researched further and it turns out it's an open issue... based on some underlying MS ApiController issue ( looks like you already responded to a guy asking this question in the past?: https://stackoverflow.com/questions/52068622/swashbuckle-maptypetype-doesnt-work-with-parameters ) – Nicholas Franceschina May 13 '19 at 15:40
  • 1
    Does anyone know how to do this in version 5.0.0-rc4? Where instead of SwaggeDocument is OpenApiDocument. – Ondra Starenko Oct 23 '19 at 11:30