-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Labels
area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapihelp wantedUp for grabs. We would accept a PR to help resolve this issueUp for grabs. We would accept a PR to help resolve this issue
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
When an endpoint returns a type containing a Dictionary
containing another type, the schema of this last type is not processed by schema transformers (see the missing "a": "b"
in Bar2
below, causing a new schema to be created).
{
"schemas": {
"Bar": {
"type": "object",
"properties": {
"value": {
"type": "integer",
"format": "int32",
"a": "b"
}
},
"a": "b"
},
"Bar2": {
"type": "object",
"properties": {
"value": {
"type": "integer",
"format": "int32"
}
}
},
"Foo": {
"type": "object",
"properties": {
"bar": {
"$ref": "#/components/schemas/Bar"
},
"bars": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/Bar2"
},
"a": "b"
}
},
"a": "b"
}
}
}
My guess is that additionalProperties
should be processed somewhere here:
aspnetcore/src/OpenApi/src/Services/Schemas/OpenApiSchemaService.cs
Lines 172 to 215 in a6ce940
private async Task InnerApplySchemaTransformersAsync(OpenApiSchema schema, | |
JsonTypeInfo jsonTypeInfo, | |
JsonPropertyInfo? jsonPropertyInfo, | |
OpenApiSchemaTransformerContext context, | |
IOpenApiSchemaTransformer transformer, | |
CancellationToken cancellationToken = default) | |
{ | |
context.UpdateJsonTypeInfo(jsonTypeInfo, jsonPropertyInfo); | |
await transformer.TransformAsync(schema, context, cancellationToken); | |
// Only apply transformers on polymorphic schemas where we can resolve the derived | |
// types associated with the base type. | |
if (schema.AnyOf is { Count: > 0 } && jsonTypeInfo.PolymorphismOptions is not null) | |
{ | |
var anyOfIndex = 0; | |
foreach (var derivedType in jsonTypeInfo.PolymorphismOptions.DerivedTypes) | |
{ | |
var derivedJsonTypeInfo = _jsonSerializerOptions.GetTypeInfo(derivedType.DerivedType); | |
if (schema.AnyOf.Count <= anyOfIndex) | |
{ | |
break; | |
} | |
await InnerApplySchemaTransformersAsync(schema.AnyOf[anyOfIndex], derivedJsonTypeInfo, null, context, transformer, cancellationToken); | |
anyOfIndex++; | |
} | |
} | |
if (schema.Items is not null) | |
{ | |
var elementTypeInfo = _jsonSerializerOptions.GetTypeInfo(jsonTypeInfo.ElementType!); | |
await InnerApplySchemaTransformersAsync(schema.Items, elementTypeInfo, null, context, transformer, cancellationToken); | |
} | |
if (schema.Properties is { Count: > 0 }) | |
{ | |
foreach (var propertyInfo in jsonTypeInfo.Properties) | |
{ | |
if (schema.Properties.TryGetValue(propertyInfo.Name, out var propertySchema)) | |
{ | |
await InnerApplySchemaTransformersAsync(propertySchema, _jsonSerializerOptions.GetTypeInfo(propertyInfo.PropertyType), propertyInfo, context, transformer, cancellationToken); | |
} | |
} | |
} | |
} |
Expected Behavior
I expected to see
{
"schemas": {
"Bar": {
"type": "object",
"properties": {
"value": {
"type": "integer",
"format": "int32",
"a": "b"
}
},
"a": "b"
},
"Foo": {
"type": "object",
"properties": {
"bar": {
"$ref": "#/components/schemas/Bar"
},
"bars": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/Bar"
},
"a": "b"
}
},
"a": "b"
}
}
}
Steps To Reproduce
Add a schema transformer like so:
options.AddSchemaTransformer((schema, _, _)
=>
{
schema.Extensions.Add("a", new OpenApiString("b"));
return Task.CompletedTask;
});
And add an endpoint that returns a type (Foo
) which contains a dictionary with another type (Bar
).
app.MapGet("/", () => new Foo());
class Foo
{
public Bar Bar { get; set; }
public Dictionary<string, Bar> Bars { get; set; }
}
class Bar
{
public int Value { get; set; }
}
Exceptions (if any)
No response
.NET Version
9.0.200-preview.0.24575.35
Anything else?
No response
Metadata
Metadata
Assignees
Labels
area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapihelp wantedUp for grabs. We would accept a PR to help resolve this issueUp for grabs. We would accept a PR to help resolve this issue