Skip to content

Commit 35a7fa7

Browse files
committed
Improve polymorphic schema handling and discriminator logic
- Default discriminator property name to "$type" if unspecified - Reuse existing derived type schemas from registry when possible - Support both string and integer discriminator values - Set discriminator property type and enum based on value type - Use resolved property name for discriminator and mapping - Enhances robustness and consistency in schema generation
1 parent 34b5f75 commit 35a7fa7

1 file changed

Lines changed: 29 additions & 6 deletions

File tree

src/SignalR.OpenApi/Generation/SignalROpenApiDocumentGenerator.cs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -601,19 +601,42 @@ private OpenApiSchema CreatePolymorphicSchema(Type type, JsonPolymorphicAttribut
601601
var derivedTypes = type.GetCustomAttributes<JsonDerivedTypeAttribute>();
602602
var schemas = new List<OpenApiSchema>();
603603
var mapping = new Dictionary<string, string>();
604+
var discriminatorPropertyName = polymorphicAttr.TypeDiscriminatorPropertyName ?? "$type";
604605

605606
foreach (var derived in derivedTypes)
606607
{
607-
var derivedSchema = CreateSchemaForType(derived.DerivedType);
608608
var schemaName = derived.DerivedType.Name;
609+
var derivedSchema = (OpenApiSchema?)null;
610+
if (this.schemaRegistry.ContainsKey(derived.DerivedType))
611+
{
612+
this.currentDocument?.Components.Schemas.TryGetValue(schemaName, out derivedSchema);
613+
}
614+
else
615+
{
616+
derivedSchema = CreateSchemaForType(derived.DerivedType);
617+
}
618+
619+
if (derivedSchema is null)
620+
{
621+
continue;
622+
}
623+
624+
var discriminatorValue = derived.TypeDiscriminator switch
625+
{
626+
string s => s,
627+
int i => i.ToString(System.Globalization.CultureInfo.InvariantCulture),
628+
_ => null,
629+
};
609630

610-
if (derived.TypeDiscriminator is string discriminatorValue)
631+
if (discriminatorValue is not null)
611632
{
612633
derivedSchema.Properties ??= new Dictionary<string, OpenApiSchema>();
613-
derivedSchema.Properties[polymorphicAttr.TypeDiscriminatorPropertyName] = new OpenApiSchema
634+
derivedSchema.Properties[discriminatorPropertyName] = new OpenApiSchema
614635
{
615-
Type = "string",
616-
Enum = [new Microsoft.OpenApi.Any.OpenApiString(discriminatorValue)],
636+
Type = derived.TypeDiscriminator is string ? "string" : "integer",
637+
Enum = derived.TypeDiscriminator is string
638+
? [new Microsoft.OpenApi.Any.OpenApiString(discriminatorValue)]
639+
: [new Microsoft.OpenApi.Any.OpenApiInteger(int.Parse(discriminatorValue, System.Globalization.CultureInfo.InvariantCulture))],
617640
};
618641

619642
mapping[discriminatorValue] = $"#/components/schemas/{schemaName}";
@@ -647,7 +670,7 @@ private OpenApiSchema CreatePolymorphicSchema(Type type, JsonPolymorphicAttribut
647670
OneOf = schemas,
648671
Discriminator = new OpenApiDiscriminator
649672
{
650-
PropertyName = polymorphicAttr.TypeDiscriminatorPropertyName,
673+
PropertyName = discriminatorPropertyName,
651674
Mapping = mapping.Count > 0 ? mapping : null,
652675
},
653676
};

0 commit comments

Comments
 (0)