Skip to content

Commit 269b050

Browse files
committed
fix: restores nullable emission for v3
Signed-off-by: Vincent Biret <vibiret@microsoft.com>
1 parent b83bdd0 commit 269b050

3 files changed

Lines changed: 48 additions & 16 deletions

File tree

src/Microsoft.OpenApi/Models/OpenApiSchema.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version
535535
writer.WriteOptionalCollection(OpenApiConstants.Enum, enumValue, (nodeWriter, s) => nodeWriter.WriteAny(s));
536536

537537
// type
538-
var serializedTypeProperty = TrySerializeTypeProperty(writer, version);
538+
TrySerializeTypeProperty(writer, version);
539539

540540
// allOf
541541
writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, callback);
@@ -580,13 +580,8 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version
580580
writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
581581

582582
// nullable
583-
if (version == OpenApiSpecVersion.OpenApi3_0 && serializedTypeProperty)
583+
if (version == OpenApiSpecVersion.OpenApi3_0)
584584
{
585-
// https://spec.openapis.org/oas/v3.0.4.html#fixed-fields-20
586-
// This keyword only takes effect if type is explicitly defined within the same Schema Object.
587-
//
588-
// If the user explicitly set IsNullable to true, we serialize it even if redundant.
589-
// But if **we** are inferring it (from oneOf/anyOf), we don't serialize it when it's redundant.
590585
SerializeNullable(writer, version);
591586
}
592587

src/Microsoft.OpenApi/Services/OpenApiV3_1ToV3SerializationConverter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public override void Visit(IOpenApiSchema schema)
4242
{
4343
JsonNullSentinel.JsonNull
4444
};
45+
concreteSchema.Type = null;
4546
}
4647
}
4748

test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,9 @@ public async Task SerializeOneOfWithNullAsV3ShouldUseNullableAsync()
964964
"""
965965
{
966966
"oneOf": [
967-
{ },
967+
{
968+
"nullable": true
969+
},
968970
{
969971
"maxLength": 10,
970972
"type": "string"
@@ -1004,7 +1006,9 @@ public async Task SerializeOneOfWithNullAndMultipleSchemasAsV3ShouldMarkItAsNull
10041006
"""
10051007
{
10061008
"oneOf": [
1007-
{ },
1009+
{
1010+
"nullable": true
1011+
},
10081012
{
10091013
"type": "string"
10101014
},
@@ -1052,7 +1056,9 @@ public async Task SerializeAnyOfWithNullAsV3ShouldUseNullableAsync()
10521056
"""
10531057
{
10541058
"anyOf": [
1055-
{ },
1059+
{
1060+
"nullable": true
1061+
},
10561062
{
10571063
"type": "object",
10581064
"properties": {
@@ -1095,7 +1101,9 @@ public async Task SerializeAnyOfWithNullAndMultipleSchemasAsV3ShouldApplyNullabl
10951101
"""
10961102
{
10971103
"anyOf": [
1098-
{ },
1104+
{
1105+
"nullable": true
1106+
},
10991107
{
11001108
"minLength": 1,
11011109
"type": "string"
@@ -1136,7 +1144,9 @@ public async Task SerializeOneOfWithOnlyNullAsV3ShouldJustBeNullableAsync()
11361144
"""
11371145
{
11381146
"oneOf": [
1139-
{ }
1147+
{
1148+
"nullable": true
1149+
}
11401150
]
11411151
}
11421152
""";
@@ -1235,7 +1245,9 @@ public async Task SerializeOneOfWithNullAndRefAsV3ShouldUseNullableAsync()
12351245
"""
12361246
{
12371247
"oneOf": [
1238-
{ },
1248+
{
1249+
"nullable": true
1250+
},
12391251
{
12401252
"$ref": "#/components/schemas/Pet"
12411253
}
@@ -1610,7 +1622,7 @@ public void ApplySemanticConversionsFromV31ToV3ConvertsNullTypeToNullEnum()
16101622

16111623
document.ApplySemanticConversions(OpenApiSpecVersion.OpenApi3_1, OpenApiSpecVersion.OpenApi3_0);
16121624

1613-
Assert.Equal(JsonSchemaType.Null, nullSchema.Type);
1625+
Assert.Null(nullSchema.Type);
16141626
var enumValues = nullSchema.Enum;
16151627
Assert.NotNull(enumValues);
16161628
Assert.Single(enumValues);
@@ -2388,7 +2400,9 @@ public async Task SerializeNullableEnumWith3_0()
23882400
var expected = """
23892401
{
23902402
"oneOf": [
2391-
{ },
2403+
{
2404+
"nullable": true
2405+
},
23922406
{
23932407
"enum": [
23942408
"A",
@@ -2458,7 +2472,29 @@ public async Task SerializeNullableTypeWith3_0()
24582472
{
24592473
var schema = CreateTypeNullSchema();
24602474
var result = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
2461-
var expected = "{ }";
2475+
var expected = """
2476+
{
2477+
"nullable": true
2478+
}
2479+
""";
2480+
2481+
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(result)));
2482+
}
2483+
2484+
[Fact]
2485+
public async Task SerializeMultipleTypesIncludingNullWith3_0EmitsNullable()
2486+
{
2487+
var schema = new OpenApiSchema
2488+
{
2489+
Type = JsonSchemaType.String | JsonSchemaType.Integer | JsonSchemaType.Null
2490+
};
2491+
2492+
var result = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
2493+
var expected = """
2494+
{
2495+
"nullable": true
2496+
}
2497+
""";
24622498

24632499
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(result)));
24642500
}

0 commit comments

Comments
 (0)