Skip to content

Commit cdebc52

Browse files
Fix AllOf behaviour when nullable
When a property is using `AnyOf` and is nullable, convert it to use `OneOf` with null instead. Resolves #3649.
1 parent 3d3575c commit cdebc52

4 files changed

Lines changed: 32 additions & 11 deletions

src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ private IOpenApiSchema GenerateSchemaForMember(
4949
? GeneratePolymorphicSchema(schemaRepository, knownTypesDataContracts)
5050
: GenerateConcreteSchema(dataContract, schemaRepository);
5151

52+
bool usingAllOf = false;
53+
5254
if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema is OpenApiSchemaReference reference)
5355
{
54-
schema = new OpenApiSchema()
55-
{
56-
AllOf = [reference],
57-
};
56+
schema = new OpenApiSchema() { AllOf = [reference] };
57+
usingAllOf = true;
5858
}
5959

6060
if (schema is OpenApiSchema concrete)
@@ -68,7 +68,22 @@ private IOpenApiSchema GenerateSchemaForMember(
6868

6969
var nullable = IsNullable(requiredAttribute, dataProperty, memberInfo);
7070

71-
SetNullable(concrete, nullable);
71+
if (usingAllOf)
72+
{
73+
// When using AllOf to extend reference schemas, we need to adjust the schema to represent
74+
// nullability correctly as a property can't be null AND a specific type at the same time.
75+
// See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/3649.
76+
if (nullable)
77+
{
78+
concrete.OneOf = schema.AllOf;
79+
concrete.OneOf.Add(new OpenApiSchema { Type = JsonSchemaType.Null });
80+
concrete.AllOf = null;
81+
}
82+
}
83+
else
84+
{
85+
SetNullable(concrete, nullable);
86+
}
7287

7388
concrete.ReadOnly = dataProperty.IsReadOnly;
7489
concrete.WriteOnly = dataProperty.IsWriteOnly;

test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=MinimalAppWithNullableEnums.Program_swaggerRequestUri=v1.DotNet10_0.verified.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848
"type": "object",
4949
"properties": {
5050
"child": {
51-
"type": "null",
52-
"allOf": [
51+
"oneOf": [
5352
{
5453
"$ref": "#/components/schemas/Child"
54+
},
55+
{
56+
"type": "null"
5557
}
5658
]
5759
},

test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=MinimalAppWithNullableEnums.Program_swaggerRequestUri=v1.DotNet8_0.verified.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848
"type": "object",
4949
"properties": {
5050
"child": {
51-
"type": "null",
52-
"allOf": [
51+
"oneOf": [
5352
{
5453
"$ref": "#/components/schemas/Child"
54+
},
55+
{
56+
"type": "null"
5557
}
5658
]
5759
},

test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=MinimalAppWithNullableEnums.Program_swaggerRequestUri=v1.DotNet9_0.verified.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848
"type": "object",
4949
"properties": {
5050
"child": {
51-
"type": "null",
52-
"allOf": [
51+
"oneOf": [
5352
{
5453
"$ref": "#/components/schemas/Child"
54+
},
55+
{
56+
"type": "null"
5557
}
5658
]
5759
},

0 commit comments

Comments
 (0)