Enhance experience for auto-populating JsonSerializerContext with required types
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Describe the bug
I was playing around with the native AoT support for the new OpenAPI feature in the .NET 9 preview.5 nightly builds (`9.0.100-preview.5.24281.15` specifically), and on rendering the document when debugging I got the following error:
```
NotSupportedException: JsonTypeInfo metadata for type 'System.Nullable`1[System.Boolean]' was not provided by TypeInfoResolver of type '[Microsoft.AspNetCore.OpenApi.OpenApiJsonSchemaContext, MartinCostello.Api.ApplicationJsonSerializerContext]'. If using source generation, ensure that all root types passed to the serializer have been annotated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically.
System.Text.Json.ThrowHelper.ThrowNotSupportedException_NoMetadataForType(Type type, IJsonTypeInfoResolver resolver)
System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, bool ensureConfigured, Nullable ensureNotNull, bool resolveIfMutable, bool fallBackToNearestAncestorType)
System.Text.Json.JsonSerializerOptions.GetTypeInfo(Type type)
JsonSchemaMapper.JsonSchemaMapper.GetJsonSchema(JsonSerializerOptions options, ParameterInfo parameterInfo, JsonSchemaMapperConfiguration configuration)
Microsoft.AspNetCore.OpenApi.OpenApiComponentService.CreateSchema(ValueTuple key)
System.Collections.Concurrent.ConcurrentDictionary.GetOrAdd(TKey key, Func valueFactory)
Microsoft.AspNetCore.OpenApi.OpenApiComponentService.GetOrCreateSchema(Type type, ApiParameterDescription parameterDescription)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetParameters(ApiDescription description)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOperation(ApiDescription description, HashSet capturedTags)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOperations(IGrouping descriptions, HashSet capturedTags)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiPaths(HashSet capturedTags)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiDocumentAsync(CancellationToken cancellationToken)
Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions+<>c__DisplayClass0_0+<b__0>d.MoveNext()
Microsoft.AspNetCore.Http.Generated.F56B68D2B55B5B7B373BA2E4796D897848BC0F04A969B1AF6260183E8B9E0BAF2__GeneratedRouteBuilderExtensionsCore+<>c__DisplayClass2_0+<g__RequestHandler|5>d.MoveNext()
Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.InvokeCore(HttpContext context)
Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
MartinCostello.Api.Middleware.CustomHttpHeadersMiddleware.Invoke(HttpContext context) in CustomHttpHeadersMiddleware.cs
```
None of my API models use `bool?`, so I was a bit confused as to what was causing the problem.
Doing a find in Visual Studio for `bool?` lead me to an optional query string parameter on one of my endpoints: [code](https://github.com/martincostello/api/blob/aa691000a84f23ee18f06420fd3b3ee1ad616968/src/API/ApiModule.cs#L152)
I'm not sure what, if anything, can be done here, but the local developer experience digging through as to what needs to be added to my custom `JsonSerializerContext` (in this case adding `[JsonSerializable(typeof(bool?))]`) for things to render isn't great, and I imagine could be quite frustrating in a larger application.
It's also a bit confusing at first, as when I think of custom JSON serialization for AoT I think of custom types, not built-in primitive parameters. It's not needed for Request Delegate Generator to work for the actual API endpoints, for example.
### Expected Behavior
Either:
- things "just work" (generate a custom `JsonSerializerContext` with a source generator for all the types known to be part of the API surface?)
- an analyser to help identify the things you need to add to your serialization context?
- ...?
### Steps To Reproduce
- Clone https://github.com/martincostello/api/pull/1504/commits/aa691000a84f23ee18f06420fd3b3ee1ad616968
- Open the solution in Visual Studio and start the debugger
- Perform an HTTP request to the `/openapi/api.json` endpoint
### Exceptions (if any)
```
NotSupportedException: JsonTypeInfo metadata for type 'System.Nullable`1[System.Boolean]' was not provided by TypeInfoResolver of type '[Microsoft.AspNetCore.OpenApi.OpenApiJsonSchemaContext, MartinCostello.Api.ApplicationJsonSerializerContext]'. If using source generation, ensure that all root types passed to the serializer have been annotated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically.
System.Text.Json.ThrowHelper.ThrowNotSupportedException_NoMetadataForType(Type type, IJsonTypeInfoResolver resolver)
System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, bool ensureConfigured, Nullable ensureNotNull, bool resolveIfMutable, bool fallBackToNearestAncestorType)
System.Text.Json.JsonSerializerOptions.GetTypeInfo(Type type)
JsonSchemaMapper.JsonSchemaMapper.GetJsonSchema(JsonSerializerOptions options, ParameterInfo parameterInfo, JsonSchemaMapperConfiguration configuration)
Microsoft.AspNetCore.OpenApi.OpenApiComponentService.CreateSchema(ValueTuple key)
System.Collections.Concurrent.ConcurrentDictionary.GetOrAdd(TKey key, Func valueFactory)
Microsoft.AspNetCore.OpenApi.OpenApiComponentService.GetOrCreateSchema(Type type, ApiParameterDescription parameterDescription)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetParameters(ApiDescription description)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOperation(ApiDescription description, HashSet capturedTags)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOperations(IGrouping descriptions, HashSet capturedTags)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiPaths(HashSet capturedTags)
Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiDocumentAsync(CancellationToken cancellationToken)
Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions+<>c__DisplayClass0_0+<b__0>d.MoveNext()
Microsoft.AspNetCore.Http.Generated.F56B68D2B55B5B7B373BA2E4796D897848BC0F04A969B1AF6260183E8B9E0BAF2__GeneratedRouteBuilderExtensionsCore+<>c__DisplayClass2_0+<g__RequestHandler|5>d.MoveNext()
Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.InvokeCore(HttpContext context)
Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
MartinCostello.Api.Middleware.CustomHttpHeadersMiddleware.Invoke(HttpContext context) in CustomHttpHeadersMiddleware.cs
```
### .NET Version
9.0.100-preview.5.24281.15
### Anything else?
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.