Swashbuckle.aspnetcore: Schema cannot be generated

Created on 8 Apr 2020  路  6Comments  路  Source: domaindrivendev/Swashbuckle.AspNetCore

After upgrading to 5.3.0 or 5.3.1 we're getting the following exception:

System.NotSupportedException: Schema cannot be generated for type System.Collections.Generic.Dictionary`2[TestWebApplication.Controllers.Enum1,System.Collections.Generic.List`1[TestWebApplication.Controllers.Class2]] as it's not supported by the System.Text.Json serializer
   at Swashbuckle.AspNetCore.SwaggerGen.JsonSerializerDataContractResolver.GetDataContractForType(Type type)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForType(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GeneratePropertySchema(DataProperty serializerMember, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateObjectSchema(DataContract dataContract, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateInlineSchema(DataContract dataContract, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.<>c__DisplayClass7_0.<GenerateReferencedSchema>b__0()
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.GetOrAdd(Type type, String schemaId, Func`1 factoryMethod)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateReferencedSchema(DataContract dataContract, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForType(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, MemberInfo memberInfo, ParameterInfo parameterInfo)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateArraySchema(DataContract dataContract, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateInlineSchema(DataContract dataContract, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForType(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, MemberInfo memberInfo, ParameterInfo parameterInfo)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreateResponseMediaType(ModelMetadata modelMetadata, SchemaRepository schemaRespository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.<>c__DisplayClass18_0.<GenerateResponse>b__2(String contentType)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponse(ApiDescription apiDescription, SchemaRepository schemaRepository, String statusCode, ApiResponseType apiResponseType)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponses(ApiDescription apiDescription, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)`

I tried to find a reason in the release notes but I didn't see any changes to the serialization or I missed something? Has this become unsupported or is this a bug? When I downgrade to 5.2.1 everything works as intended.

I've created a simple solution to reproduce the problem: TestWebApplication.zip
But the general idea is this:

public enum Enum1
{
    Value1,
    Value2
}

public class Class1
{
    public Dictionary<Enum1, List<Class2>> Params { get; set; } = new Dictionary<Enum1, List<Class2>>();
}

public class Class2
{
    public string Property { get; set; } = "Test";
}

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    [HttpGet]
    public IEnumerable<Class1> Get()
    {
        return new []{ new Class1() };
    }
}

Most helpful comment

System.Text.Json serializer doesn't support non string dictionary keys. You need to add Swashbuckle.AspNetCore.Newtonsoft nuget package and call AddSwaggerGenNewtonsoftSupport() on your IServiceCollection to register it as default serializer.

All 6 comments

System.Text.Json serializer doesn't support non string dictionary keys. You need to add Swashbuckle.AspNetCore.Newtonsoft nuget package and call AddSwaggerGenNewtonsoftSupport() on your IServiceCollection to register it as default serializer.

Just a question for mantainers... shouldn't changing the default serializer be a breaking change? Considering all the limitations that System.Text.Json currently has, I would say yes, but not an expert on semantic versioning 馃槃

@adrian-lopez-softtek honoring STJ by default _is_ a breaking change _but_ that change was introduced in v5.0.0 - a major version increment. It's well documented in the 5.0.0 release notes.

Throwing the exception on a type that's unsupported by that serializer was introduced in 5.3.1 because I consider that to be a "bug fix".

Yeah, makes sense! My bad for not reading the release notes of version first 5 release. Thought it was changed now because didn't have the errors before. Thanks for the response!

Thanks! All makes sense now!

Just because Dictionary serialization is not supported out-of-the-box doesn't mean we can't add it ourselves.

This won't work ATM because JsonSerializerDataContractResolver has a hardcoded exception for dictionaries with enums as keys, regardless of the converters provided by the JsonSerializerOptions. This should not be the case.

Was this page helpful?
0 / 5 - 0 ratings