Skip to content

Commit 12fb7b0

Browse files
authored
Merge branch 'main' into dev/ygerges/multiple-types-3
2 parents 39ed47e + 655c2c8 commit 12fb7b0

7 files changed

Lines changed: 284 additions & 34 deletions

File tree

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434

3535
- name: Initialize CodeQL
3636
id: init_codeql
37-
uses: github/codeql-action/init@v4.37.2
37+
uses: github/codeql-action/init@v4.37.3
3838
with:
3939
queries: security-and-quality
4040

@@ -54,6 +54,6 @@ jobs:
5454
5555
- name: Perform CodeQL Analysis
5656
id: analyze_codeql
57-
uses: github/codeql-action/analyze@v4.37.2
57+
uses: github/codeql-action/analyze@v4.37.3
5858

5959
# Built with ❤ by [Pipeline Foundation](https://pipeline.foundation)

.github/workflows/sonarcloud.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
runs-on: windows-latest
3636
steps:
3737
- name: Set up JDK 17
38-
uses: actions/setup-java@v5
38+
uses: actions/setup-java@v5.6.0
3939
with:
4040
distribution: 'adopt'
4141
java-version: 17

src/Microsoft.OpenApi/Models/OpenApiSchema.cs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version
550550
}
551551

552552
// type
553-
var serializedTypeProperty = TrySerializeTypePropertyForVersion3AndLater(writer, version, callback);
553+
SerializeTypePropertyForVersion3AndLater(writer, version, callback);
554554

555555
// allOf
556556
writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, callback);
@@ -595,13 +595,13 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version
595595
writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
596596

597597
// nullable
598-
if (version == OpenApiSpecVersion.OpenApi3_0 && serializedTypeProperty)
598+
if (version == OpenApiSpecVersion.OpenApi3_0)
599599
{
600600
// https://spec.openapis.org/oas/v3.0.4.html#fixed-fields-20
601601
// This keyword only takes effect if type is explicitly defined within the same Schema Object.
602602
//
603-
// If the user explicitly set IsNullable to true, we serialize it even if redundant.
604-
// But if **we** are inferring it (from oneOf/anyOf), we don't serialize it when it's redundant.
603+
// We don't care to avoid an unnecessary serialization.
604+
// So, we attempt to serialize it regardless of whether or not a type property was serialized.
605605
SerializeNullable(writer, version);
606606
}
607607

@@ -838,7 +838,7 @@ private void SerializeAsV2(
838838
writer.WriteStartObject();
839839

840840
// type
841-
TrySerializeTypePropertyForVersion2(writer);
841+
SerializeTypePropertyForVersion2(writer);
842842

843843
// description
844844
writer.WriteProperty(OpenApiConstants.Description, Description);
@@ -1006,21 +1006,18 @@ private void SerializeAsV2(
10061006
writer.WriteEndObject();
10071007
}
10081008

1009-
private bool TrySerializeTypePropertyForVersion2(IOpenApiWriter writer)
1009+
private void SerializeTypePropertyForVersion2(IOpenApiWriter writer)
10101010
{
1011-
if (Type is not { } type)
1011+
if (Type is not { } type || type == JsonSchemaType.Null)
10121012
{
1013-
return false;
1013+
return;
10141014
}
10151015

10161016
var typeWithoutNull = type & ~JsonSchemaType.Null;
1017-
if (typeWithoutNull != 0 && !HasMultipleTypes(typeWithoutNull))
1017+
if (!HasMultipleTypes(typeWithoutNull))
10181018
{
10191019
writer.WriteProperty(OpenApiConstants.Type, typeWithoutNull.ToFirstIdentifier());
1020-
return true;
10211020
}
1022-
1023-
return false;
10241021
}
10251022

10261023
/// <summary>
@@ -1030,18 +1027,18 @@ private bool TrySerializeTypePropertyForVersion2(IOpenApiWriter writer)
10301027
/// true if the Type was serializable using "type" property, and false if
10311028
/// it serialized using anyOf/oneOf or if it couldn't be serialized at all.
10321029
/// </returns>
1033-
private bool TrySerializeTypePropertyForVersion3AndLater(IOpenApiWriter writer, OpenApiSpecVersion version, Action<IOpenApiWriter, IOpenApiSerializable> callback)
1030+
private void SerializeTypePropertyForVersion3AndLater(IOpenApiWriter writer, OpenApiSpecVersion version, Action<IOpenApiWriter, IOpenApiSerializable> callback)
10341031
{
10351032
if (Type is not { } type)
10361033
{
1037-
return false;
1034+
return;
10381035
}
10391036

10401037
if (version == OpenApiSpecVersion.OpenApi3_0)
10411038
{
10421039
if (type == JsonSchemaType.Null)
10431040
{
1044-
return false;
1041+
return;
10451042
}
10461043

10471044
var typeWithoutNull = type & ~JsonSchemaType.Null;
@@ -1061,18 +1058,18 @@ where typeWithoutNull.HasFlag(flag)
10611058
if (canWriteAsAnyOf)
10621059
{
10631060
writer.WriteOptionalCollection(OpenApiConstants.AnyOf, ConstructChildSchemasForTypes(arrayWithoutNull, hasNull), callback);
1064-
return false;
1061+
return;
10651062
}
10661063
else if (canWriteAsOneOf)
10671064
{
10681065
writer.WriteOptionalCollection(OpenApiConstants.OneOf, ConstructChildSchemasForTypes(arrayWithoutNull, hasNull), callback);
1069-
return false;
1066+
return;
10701067
}
10711068
}
10721069
else
10731070
{
10741071
writer.WriteProperty(OpenApiConstants.Type, arrayWithoutNull[0].ToSingleIdentifier());
1075-
return true;
1072+
return;
10761073
}
10771074
}
10781075
else
@@ -1089,12 +1086,8 @@ where type.HasFlag(flag)
10891086
{
10901087
writer.WriteProperty(OpenApiConstants.Type, array[0].ToSingleIdentifier());
10911088
}
1092-
1093-
return true;
10941089
}
10951090

1096-
return false;
1097-
10981091
static OpenApiSchema[] ConstructChildSchemasForTypes(JsonSchemaType[] types, bool hasNull)
10991092
{
11001093
var schemas = new OpenApiSchema[types.Length + (hasNull ? 1 : 0)];

src/Microsoft.OpenApi/Reader/JsonNodeHelper.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ public static List<JsonNode> CreateListOfAny(this JsonNode? node, ParsingContext
4242
throw new OpenApiReaderException("Cannot create a list from this type of node.", context);
4343
}
4444

45-
return jsonArray.OfType<JsonNode>().ToList();
45+
var list = new List<JsonNode>(jsonArray.Count);
46+
foreach (var element in jsonArray)
47+
{
48+
list.Add(element ?? JsonNullSentinel.JsonNull);
49+
}
50+
51+
return list;
4652
}
4753

4854
public static List<T> CreateSimpleList<T>(this JsonNode? node, Func<JsonNode, OpenApiDocument?, T> map, OpenApiDocument? openApiDocument, ParsingContext context)

src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,13 @@ public static IOpenApiSchema LoadSchema(JsonNode node, OpenApiDocument hostDocum
413413
}
414414
}
415415

416+
if (schema.Type is null && schema.Enum is { Count: 1 } &&
417+
schema.Enum[0].IsJsonNullSentinel())
418+
{
419+
schema.Enum = null;
420+
schema.Type = JsonSchemaType.Null;
421+
}
422+
416423
return schema;
417424
}
418425
}

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,8 @@ public async Task SerializeOneOfWithNullAsV3ShouldUseNullableAsync()
965965
{
966966
"enum": [
967967
null
968-
]
968+
],
969+
"nullable": true
969970
},
970971
{
971972
"maxLength": 10,
@@ -1009,7 +1010,8 @@ public async Task SerializeOneOfWithNullAndMultipleSchemasAsV3ShouldMarkItAsNull
10091010
{
10101011
"enum": [
10111012
null
1012-
]
1013+
],
1014+
"nullable": true
10131015
},
10141016
{
10151017
"type": "string"
@@ -1061,7 +1063,8 @@ public async Task SerializeAnyOfWithNullAsV3ShouldUseNullableAsync()
10611063
{
10621064
"enum": [
10631065
null
1064-
]
1066+
],
1067+
"nullable": true
10651068
},
10661069
{
10671070
"type": "object",
@@ -1108,7 +1111,8 @@ public async Task SerializeAnyOfWithNullAndMultipleSchemasAsV3ShouldApplyNullabl
11081111
{
11091112
"enum": [
11101113
null
1111-
]
1114+
],
1115+
"nullable": true
11121116
},
11131117
{
11141118
"minLength": 1,
@@ -1153,7 +1157,8 @@ public async Task SerializeOneOfWithOnlyNullAsV3ShouldJustBeNullableAsync()
11531157
{
11541158
"enum": [
11551159
null
1156-
]
1160+
],
1161+
"nullable": true
11571162
}
11581163
]
11591164
}
@@ -1256,7 +1261,8 @@ public async Task SerializeOneOfWithNullAndRefAsV3ShouldUseNullableAsync()
12561261
{
12571262
"enum": [
12581263
null
1259-
]
1264+
],
1265+
"nullable": true
12601266
},
12611267
{
12621268
"$ref": "#/components/schemas/Pet"
@@ -2050,7 +2056,8 @@ public async Task SerializeNullableEnumWith3_0()
20502056
{
20512057
"enum": [
20522058
null
2053-
]
2059+
],
2060+
"nullable": true
20542061
},
20552062
{
20562063
"enum": [
@@ -2099,7 +2106,8 @@ public async Task SerializeNullableTypeWith3_0()
20992106
{
21002107
"enum": [
21012108
null
2102-
]
2109+
],
2110+
"nullable": true
21032111
}
21042112
""";
21052113

0 commit comments

Comments
 (0)