SwaggerGen isn't recognizing my Newtonsoft JsonProperty attributes, despite AddSwaggerGenNewtonsoftSupport call

I've just recently upgraded from Swashbuckle.AspNetCore.SwaggerGen 4.0.1 to 6.4.0, and now the Newtonsoft Json attributes ([JsonProperty(...)] and the like) are being ignored. In particular, [JsonProperty(PropertyName = "key")] is used all over my codebase to rename properties, and those new names are not reflected in the swagger.json.

Unlike this other question, I've tried services.AddSwaggerGenNewtonsoftSupport(), and it's not working like it should.

This is a .Net 6.0 project.

Relevant code snippets

Packages installed

 <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="6.4.0" /> 

Startup.cs

I'll admit I just started spamming AddNewtonsoftJson() once I saw there was more than one place I could/should put it. The AddControllers().AddNewtonsoftJson() and AddMvcCore().AddNewtonsoftJson() calls are the latest flailing I've tried, the builder.AddNewtonsoftJson() was the first attempt.

 var builder = services.AddMvcCore(x => { x.EnableEndpointRouting = false; }); builder.AddNewtonsoftJson(x => { x.AllowInputFormatterExceptionMessages = false; // Default enum serialization: as a string, not a number. x.SerializerSettings.Converters.Add(new StringEnumConverter()); // don't serialize nulls x.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; x.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore; }); builder.Services.AddControllers().AddNewtonsoftJson() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); // Homemade all-Swagger-init function, see SwaggerConfig.cs services.AddSwaggerPage(); 

SwaggerConfig.cs

You can see services.AddSwaggerGenNewtonsoftSupport() is called (probably correctly?) here.

 public static void AddSwaggerPage(this IServiceCollection services) { services.AddSwaggerGen(); services.ConfigureSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Version = ..., Title = ..., Description = ... }); services.AddSwaggerGenNewtonsoftSupport(); ...and a bunch of auth stuff... } } 

Note that I've tried putting the AddSwaggerGenNewtonsoftSupport outside of the ConfigureSwaggerGen call, but doing so caused any fetch of swagger.json to hit HTTP 500. Here's the interesting part of the exception:

{ "Error": { "Message": "Failed to generate Operation for action - Project.Host.Controllers.ThingController.GetThingSettings (Project.Host). See inner exception", "Data": {}, "InnerException": { "Message": "Failed to generate schema for type - GetThingSettings. See inner exception", "Data": {}, "InnerException": { "ClassName": "System.NullReferenceException", "Message": "Object reference not set to an instance of an object.", "Data": null, "InnerException": null, "HelpURL": null, "StackTraceString": " at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForMember(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, DataProperty dataProperty)\r\n at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.CreateObjectSchema(DataContract dataContract, SchemaRepository schemaRepository)\r\n at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateReferencedSchema(DataContract dataContract, SchemaRepository schemaRepository, Func`1 definitionFactory)\r\n at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository)\r\n at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForType(Type modelType, SchemaRepository schemaRepository)\r\n at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)", 

GetThingSettings is boring-but-nested, with several basic types in it. The weirdest one is a Dictionary<ThingEnum, BasicValuesClass>, where ThingEnum is an enum.

public enum ThingEnum { Thing1, Thing2, Thing3 } public class GetThingSettings { public Dictionary<string, List<int>> Lists { get; set; } public Dictionary<ThingEnum, ThingEnabled> ThingEnabled { get; set; } } public class ThingEnabled { public bool? All { get; set; } public List<int> Included { get; set; } public List<int> Excluded { get; set; } } 

Code that generates the wrong property name in swagger.json, from an in-house Nuget package

namespace Thingy { public class Document { // This right here gets ignored. The generated swagger.json has this as "eTag", not "_etag". [JsonProperty(PropertyName = "_etag", NullValueHandling = NullValueHandling.Ignore)] public string ETag { get; set; } } } 

So: what error am I making in making Swagger recognize the Newtonsoft attributes?

1 Answer

I would try use services.AddSwaggerGenNewtonsoftSupport() outside services.ConfigureSwaggerGen(), like in the example and README.

Example from README:

services.AddMvc(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen() 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like