Swashbuckle.aspnetcore: JsonProperty(ItemConverterType = typeof(StringEnumConverter)) not recognized without DescribeAllEnumsAsStrings()

Created on 30 Oct 2019  路  11Comments  路  Source: domaindrivendev/Swashbuckle.AspNetCore

Hi. In Swashbuckle.AspNetCore 5.0.0-rc4 method SwaggerGenOptions.DescribeAllEnumsAsStrings() marked as Obsolete. But without it attribute [Newtonsoft.Json.JsonProperty(ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))] is not working properly. See example below.

public class Program
{
    public static void Main(string[] args)
        => Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(b => b.UseStartup<Startup>())
            .Build()
            .Run();
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
        => services
            .AddSwaggerGen(c => c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" }))
            .AddControllers();

    public void Configure(IApplicationBuilder app)
        => app
            .UseSwagger()
            .UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"))
            .UseRouting()
            .UseEndpoints(endpoints => endpoints.MapControllers());
}

[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter), true)]
public enum OkEnum
{
    Freezing, Bracing, Chilly, Cool
}

public enum BadEnum
{
    Freezing, Bracing, Chilly, Cool
}

public class WeatherForecast
{
    public DateTime Date { get; set; }
    public OkEnum OkValue { get; set; }
    [Newtonsoft.Json.JsonProperty(ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
    public List<BadEnum> BadValues { get; set; }
}

[ApiController]
[Route("weather")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
        => Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            OkValue = OkEnum.Cool,
            BadValues = new List<BadEnum> { BadEnum.Cool }
        });
}

sw

With SwaggerGenOptions.DescribeAllEnumsAsStrings()

sw3

Most helpful comment

@artfulsage - You're using Newtonsoft attributes, but Swashbuckle.AspNetCore 5.x uses System.Text.Json by default.

To fix this, either:

  • Use [JsonConverter(typeof(JsonStringEnumConverter))] from the System.Text.Json.Serialization namespace on your enum declarations

  • Or to convert all enums to strings, in your ConfigureServices method, add the following after AddControllers():

.AddJsonOptions(options => {
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
});
  • If you need to use Newtonsoft for serialization, add the Swashbuckle.AspNetCore.Newtonsoft Nuget package and call services.AddSwaggerGenNewtonsoftSupport() in Startup.cs -> ConfigureServices

All 11 comments

I have the same problem

@artfulsage can you elaborate a little more on your usecase? I do understand the issue you're reporting but I guess I'm not understanding why you wouldn't just use the JsonConverterAttribute on the enum definition itself (as opposed to the property that uses it) - i.e. as you've demonstrated with OkEnum above.

The only reason I can think of to NOT do this is if you wanted to serialize the enum as a string in some cases (e.g. when part of a certain property) and as an integer in others. However, the DescribeAllEnumsAsStrings is a global setting applied to _all enums_ and therefore wouldn't support this scenario anyway.

I have the same problem (using 5.0.0 RC-5). I have tried adding a global JsonConvert (StringEnumConverter) to json serializer settings along with DescribeAllEnumsAsStrings, just DescribeAllEnumsAsStrings , StringEnumConverter on the enum itself. None of these options seem to work, the enums still return as integers. I am not sure what other information to display for this issue, but let me know.

@artfulsage - You're using Newtonsoft attributes, but Swashbuckle.AspNetCore 5.x uses System.Text.Json by default.

To fix this, either:

  • Use [JsonConverter(typeof(JsonStringEnumConverter))] from the System.Text.Json.Serialization namespace on your enum declarations

  • Or to convert all enums to strings, in your ConfigureServices method, add the following after AddControllers():

.AddJsonOptions(options => {
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
});
  • If you need to use Newtonsoft for serialization, add the Swashbuckle.AspNetCore.Newtonsoft Nuget package and call services.AddSwaggerGenNewtonsoftSupport() in Startup.cs -> ConfigureServices

@domaindrivendev, @jcoutch thanks for your feedback!

  • My enum is located in separated database project. And that's why I don't want to put any code for serialization there (JsonConverterAttribute).

  • Addition of services.AddSwaggerGenNewtonsoftSupport() seems not working in my real project.

  • But this works fine!

.AddJsonOptions(options => {
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
});

@domaindrivendev it might be helpful to add that to the docs/WIKI (FAQ) : services.AddSwaggerGenNewtonsoftSupport() for future reference, seems like it is a commonly asked question

@ddeisadzevp - I found it right on the main page:
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md#systemtextjson-stj-vs-newtonsoft

@artfulsage, when you use services.AddSwaggerGenNewtonsoftSupport(), then ensure that you add it _after_ you add services.AddSwaggerGen(...); otherwise, it won't work.

@domaindrivendev @jcoutch @tobyartisan perhaps I do something wrong but this code still does not work

netcoreapp3.1
Newtonsoft.Json 12.0.3
Swashbuckle.AspNetCore 5.2.1
Swashbuckle.AspNetCore.Newtonsoft 5.2.1

public class Program
{
  public static void Main(string[] args)
    => Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(b => b.UseStartup<Startup>())
      .Build()
      .Run();
}

public class Startup
{
  public void ConfigureServices(IServiceCollection services)
  {
    services
      .AddMvc()
      .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
      .AddNewtonsoftJson();

    services
      .AddSwaggerGen(c => c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" }))
      .AddSwaggerGenNewtonsoftSupport();
  }

  public void Configure(IApplicationBuilder app)
    => app
      .UseSwagger()
      .UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"))
      .UseRouting()
      .UseEndpoints(endpoints => endpoints.MapControllers());
}

public enum BadEnum
{
  Freezing, Bracing, Chilly, Cool
}

public class WeatherForecast
{
  public DateTime Date { get; set; }
  [Newtonsoft.Json.JsonProperty(ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
  public List<BadEnum> BadValues { get; set; }
}

[ApiController]
[Route("weather")]
public class WeatherForecastController : ControllerBase
{
  [HttpGet]
  public IEnumerable<WeatherForecast> Get()
    => Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
      Date = DateTime.Now.AddDays(index),
      BadValues = new List<BadEnum> { BadEnum.Cool }
    });
}

Screenshot_2020-03-24 Swagger UI

Screenshot_2020-03-24 Screenshot

@artfulsage Do you need to do this bit?

.AddJsonOptions(options => {
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
});

@artfulsage - unfortunately ItemConverterType isn't currently supported. As mentioned above, if you decorate your enum class directly as follows - the enum will be described correctly.

[JsonConverter(typeof(StringEnumConverter))]
public enum BadEnum
{
    Freezing, Bracing, Chilly, Cool
}

However, it seems this may not be feasible for you. As many of the comments in this issue have deviated from the original, I think it would be best to create a new issue that specifically addresses the lack of support for enum serialization behavior that's configured via ItemConverterType

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mrmartan picture mrmartan  路  3Comments

flipchart picture flipchart  路  4Comments

gabeluci picture gabeluci  路  3Comments

JoelAdamWeiss picture JoelAdamWeiss  路  4Comments

voroninp picture voroninp  路  3Comments