OpenApi ignores JsonNumberHandling.WriteAsString #58882
Open
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
When a property has the attribute JsonNumberHandling(JsonNumberHandling.AllowReadingFromString|JsonNumberHandling.WriteAsString)
, OpenApi still describes the property with the native type and not a string
Expected Behavior
When using JsonNumberHandling.WriteAsString
I expect the OpenApi specification to report the propery as string
"prop": {
"type": "string",
}
Steps To Reproduce
- Create a new default asp.net webapi for dotnet 9.
- Run the project and navigate to
/openapi/v1.json
- The
temperatureC
property is listed as integer:
"temperatureC": {
"type": "integer",
"format": "int32"
},
- In weatherforcast.cs add an attribute to the
temperatureC
property
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString|JsonNumberHandling.WriteAsString)]
public int TemperatureC { get; set; }
- Run the project and navigate to
/weatherforecast
and seetemperatureC
is a string.
[{"date":"2024-11-12","temperatureC":"11","temperatureF":51,"summary":"Balmy"},{"date":"2024-11-13","temperatureC":"3","temperatureF":37,"summary":"Warm"}}
- Navigate to
/openapi/v1.json
- The
temperatureC
property is still listed as an integer:
"temperatureC": {
"type": "integer",
"format": "int32"
},
Exceptions (if any)
No response
.NET Version
9.0.100-rc.1.24452.12
Anything else?
A workaround is to add a SchemaTransformer like
internal sealed class JsonNumberHandlerSchemaTransformer : IOpenApiSchemaTransformer
{
public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext context, CancellationToken cancellationToken)
{
var properties = context.JsonTypeInfo.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(prop => prop.GetCustomAttribute<JsonNumberHandlingAttribute>()?.Handling.HasFlag(JsonNumberHandling.WriteAsString) ?? false)
.Select(prop => prop.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name ??
context.JsonTypeInfo.Options.PropertyNamingPolicy?.ConvertName(prop.Name) ??
prop.Name)
.Where(schema.Properties.ContainsKey);
foreach (var property in properties)
{
schema.Properties[property].Type = "string";
}
return Task.CompletedTask;
}
}
but this is using reflection and probably missing some other details.