Skip to content

When using JsonPolymorphic with derived types that share a common base class and have similar property structures, the OpenAPI generator throws an exception during schema generation. #62068

Open
@LiHaoGit

Description

@LiHaoGit

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When using JsonPolymorphic with derived types that share a common base class and have similar property structures, the OpenAPI generator throws an exception during schema generation.

Data.cs

using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.HttpResults;

public class StepAnswer
{
    public List<Base> Answers { get; set; } = [];
}

public static class Api
{
    public static Ok<StepAnswer> Api1()
    {
        throw new NotImplementedException();
    }
    public static Ok<Base> Api2()
    {
        throw new NotImplementedException();
    }
}


[JsonPolymorphic(TypeDiscriminatorPropertyName = "_t")]
[JsonDerivedType(typeof(BaseA), typeDiscriminator: "BaseA")]
[JsonDerivedType(typeof(BaseB), typeDiscriminator: "BaseB")]
public abstract class Base
{
}


public class BaseA : Base
{
    public Dictionary<string, List<string>>? Input { get; set; }
}

public class BaseB : Base
{
    public Dictionary<string, List<string>>? Input { get; set; }
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.MapGet("/api1", Api.Api1);
app.MapGet("/api2", Api.Api2);

app.Run();

Expected Behavior

OpenAPI schema should be generated without throwing an exception.

Steps To Reproduce

reproduce
dotnet run
curl http://localhost:5148/openapi/v1.json

Exceptions (if any)

System.ArgumentException: An item with the same key has already been added. Key: BaseBaseB
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Microsoft.AspNetCore.OpenApi.OpenApiSchemaReferenceTransformer.TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.ApplyTransformersAsync(OpenApiDocument document, IServiceProvider scopedServiceProvider, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiDocumentAsync(IServiceProvider scopedServiceProvider, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.OpenApi.OpenApiDocumentService.GetOpenApiDocumentAsync(IServiceProvider scopedServiceProvider, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.<>c__DisplayClass0_0.<<MapOpenApi>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Http.Generated.<GeneratedRouteBuilderExtensions_g>F56B68D2B55B5B7B373BA2E4796D897848BC0F04A969B1AF6260183E8B9E0BAF2__GeneratedRouteBuilderExtensionsCore.<>c__DisplayClass2_0.<<MapGet0>g__RequestHandler|5>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

.NET Version

9.0.201

Anything else?

Microsoft.AspNetCore.OpenApi 9.03

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapi

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions