ITADN

OpenAPI duplicates a polymorphic union case when the union is used as a property

#68653Openverdie-g 创建于 3 天前
feature-openapiarea-minimal
V
verdie-gcommented
### Is there an existing issue for this? - [x] I have searched the existing issues ### Describe the bug When a C# union contains a polymorphic type and the union is used as a property of another type, the generated OpenAPI document contains two components for the polymorphic type. The repro defines: ```csharp public sealed record Envelope(OneOrManyAnimal? Data); public union OneOrManyAnimal(Animal, IReadOnlyList<Animal>); ``` `Animal` is a polymorphic base type with `Cat` and `Dog` derived types. The generated components include both `Animal` and `OneOrManyAnimalAnimal`. The latter is a duplicate of the `Animal` hierarchy. The union uses the duplicate for its single-value case but uses `Animal` for the collection case: ```json "OneOrManyAnimal": { "anyOf": [ { "$ref": "#/components/schemas/OneOrManyAnimalAnimal" }, { "type": "array", "items": { "$ref": "#/components/schemas/Animal" } } ] } ``` Returning `OneOrManyAnimal` directly from the endpoint does not produce the duplicate. It appears only when the union is nested in Envelope. ### Expected Behavior Both union cases should reuse the existing `Animal` component: ```json "OneOrManyAnimal": { "anyOf": [ { "$ref": "#/components/schemas/Animal" }, { "type": "array", "items": { "$ref": "#/components/schemas/Animal" } } ] } ``` `OneOrManyAnimalAnimal` should not be generated. ### Steps To Reproduce Run the following command: ```bash ASPNETCORE_URLS=http://localhost:5000 dotnet run - <<'EOF' #:sdk Microsoft.NET.Sdk.Web #:package Microsoft.AspNetCore.OpenApi@11.0.0-preview.7.26381.103 #:property LangVersion=preview #:property EnableRequestDelegateGenerator=false using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; var builder = WebApplication.CreateBuilder(args); builder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver()); builder.Services.AddOpenApi(); var app = builder.Build(); app.MapOpenApi(); app.MapGet("/animals", () => new Envelope(new OneOrManyAnimal(new Cat("Milo")))); app.Run(); public sealed record Envelope(OneOrManyAnimal? Data); public union OneOrManyAnimal(Animal, IReadOnlyList<Animal>); [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] [JsonDerivedType(typeof(Cat), "cats")] [JsonDerivedType(typeof(Dog), "dogs")] public abstract record Animal(string Name); public sealed record Cat(string Name) : Animal(Name); public sealed record Dog(string Name) : Animal(Name); EOF ``` In another terminal, inspect the generated document: ```bash curl --silent http://localhost:5000/openapi/v1.json | jq '.components.schemas | keys' ``` The generated schema components include: ```json [ "Animal", "AnimalCat", "AnimalDog", "Envelope", "OneOrManyAnimal", "OneOrManyAnimalAnimal" ] ``` The duplicate can also be seen directly with: ```bash curl --silent http://localhost:5000/openapi/v1.json | jq '.components.schemas.OneOrManyAnimal' ``` which returns: ```json { "anyOf": [ { "$ref": "#/components/schemas/OneOrManyAnimalAnimal" }, { "type": "array", "items": { "$ref": "#/components/schemas/Animal" } } ] } ``` ### Exceptions (if any) _No response_ ### .NET Version 11.0.100-preview.7.26381.103 ### Anything else? Microsoft.AspNetCore.OpenApi 11.0.0-preview.7.26381.103 .NET SDK: Version: 11.0.100-preview.7.26381.103 Commit: e2c1e00b3d Workload version: 11.0.100-manifests.779dc26a MSBuild version: 18.10.0-1.26381.103+e2c1e00b3 Runtime Environment: OS Name: Mac OS X OS Version: 26.2 OS Platform: Darwin RID: osx-arm64 Host: Version: 11.0.0-preview.7.26381.103 Architecture: arm64 Commit: e2c1e00b3d
1 条评论