Skip to content

Commit f0ff148

Browse files
committed
Do not emit type:object when schema type is only nullable
1 parent 5e456de commit f0ff148

File tree

9 files changed

+109
-22
lines changed

9 files changed

+109
-22
lines changed

src/Microsoft.OpenApi/Models/OpenApiSchema.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,15 +765,13 @@ Extensions is not null &&
765765
}
766766
else if (!HasMultipleTypes(type.Value))
767767
{
768-
769768
switch (version)
770769
{
771770
case OpenApiSpecVersion.OpenApi3_1 when isNullable:
772771
UpCastSchemaTypeToV31(type.Value, writer);
773772
break;
774773
case OpenApiSpecVersion.OpenApi3_0 when isNullable && type.Value == JsonSchemaType.Null:
775774
writer.WriteProperty(OpenApiConstants.Nullable, true);
776-
writer.WriteProperty(OpenApiConstants.Type, JsonSchemaType.Object.ToFirstIdentifier());
777775
break;
778776
case OpenApiSpecVersion.OpenApi3_0 when isNullable && type.Value != JsonSchemaType.Null:
779777
writer.WriteProperty(OpenApiConstants.Nullable, true);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ internal static partial class OpenApiV3Deserializer
159159
"type",
160160
(o, n, _) => {
161161
var type = n.GetScalarValue()?.ToJsonSchemaType();
162-
// so we don't loose the value from nullable
162+
// so we don't lose the value from nullable
163163
if (o.Type.HasValue)
164164
o.Type |= type;
165165
else

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,10 @@ internal static partial class OpenApiV31Deserializer
286286
var nullable = bool.Parse(value);
287287
if (nullable) // if nullable, convert type into an array of type(s) and null
288288
{
289-
o.Type |= JsonSchemaType.Null;
289+
if (o.Type.HasValue)
290+
o.Type |= JsonSchemaType.Null;
291+
else
292+
o.Type = JsonSchemaType.Null;
290293
}
291294
}
292295
}
@@ -392,8 +395,11 @@ public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocu
392395

393396
if (schema.Extensions is not null && schema.Extensions.ContainsKey(OpenApiConstants.NullableExtension))
394397
{
395-
var type = schema.Type;
396-
schema.Type = type | JsonSchemaType.Null;
398+
if (schema.Type.HasValue)
399+
schema.Type |= JsonSchemaType.Null;
400+
else
401+
schema.Type = JsonSchemaType.Null;
402+
397403
schema.Extensions.Remove(OpenApiConstants.NullableExtension);
398404
}
399405

test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22
// Licensed under the MIT license.
33

44
using System.IO;
5-
using FluentAssertions;
6-
using Microsoft.OpenApi.Reader.V2;
7-
using Xunit;
8-
using Microsoft.OpenApi.Reader.ParseNodes;
9-
using Microsoft.OpenApi.Models;
10-
using Microsoft.OpenApi.Extensions;
115
using System.Text.Json.Nodes;
12-
using System.Collections.Generic;
6+
using System.Threading.Tasks;
7+
using FluentAssertions;
138
using FluentAssertions.Equivalency;
9+
using Microsoft.OpenApi.Extensions;
10+
using Microsoft.OpenApi.Models;
1411
using Microsoft.OpenApi.Models.References;
12+
using Microsoft.OpenApi.Reader;
13+
using Microsoft.OpenApi.Reader.ParseNodes;
14+
using Microsoft.OpenApi.Reader.V2;
15+
using Microsoft.OpenApi.Tests;
1516
using Microsoft.OpenApi.Writers;
16-
using Microsoft.OpenApi.Models.Interfaces;
17+
using Xunit;
1718

1819
namespace Microsoft.OpenApi.Readers.Tests.V2Tests
1920
{
@@ -98,6 +99,7 @@ public void ParseSchemaWithEnumShouldSucceed()
9899
.Excluding((IMemberInfo memberInfo) =>
99100
memberInfo.Path.EndsWith("Parent")));
100101
}
102+
101103
[Fact]
102104
public void PropertiesReferenceShouldWork()
103105
{
@@ -152,5 +154,42 @@ public void PropertiesReferenceShouldWork()
152154
);
153155
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(json), expected));
154156
}
157+
158+
[Fact]
159+
public async Task SerializeSchemaWithNullableShouldSucceed()
160+
{
161+
// Arrange
162+
var expected = @"type: string
163+
x-nullable: true";
164+
165+
var path = Path.Combine(SampleFolderPath, "schemaWithNullableExtension.yaml");
166+
167+
// Act
168+
var schema = await OpenApiModelFactory.LoadAsync<OpenApiSchema>(path, OpenApiSpecVersion.OpenApi2_0, new(), SettingsFixture.ReaderSettings);
169+
170+
var writer = new StringWriter();
171+
schema.SerializeAsV2(new OpenApiYamlWriter(writer));
172+
var schemaString = writer.ToString();
173+
174+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), schemaString.MakeLineBreaksEnvironmentNeutral());
175+
}
176+
177+
[Fact]
178+
public async Task SerializeSchemaWithOnlyNullableShouldSucceed()
179+
{
180+
// Arrange
181+
var expected = @"x-nullable: true";
182+
183+
var path = Path.Combine(SampleFolderPath, "schemaWithOnlyNullableExtension.yaml");
184+
185+
// Act
186+
var schema = await OpenApiModelFactory.LoadAsync<OpenApiSchema>(path, OpenApiSpecVersion.OpenApi2_0, new(), SettingsFixture.ReaderSettings);
187+
188+
var writer = new StringWriter();
189+
schema.SerializeAsV2(new OpenApiYamlWriter(writer));
190+
var schemaString = writer.ToString();
191+
192+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), schemaString.MakeLineBreaksEnvironmentNeutral());
193+
}
155194
}
156195
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
type: string
2+
x-nullable: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x-nullable: true

test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,22 @@
33

44
using System.Collections.Generic;
55
using System.IO;
6+
using System.Net.Http;
67
using System.Text.Json.Nodes;
8+
using System.Threading.Tasks;
79
using FluentAssertions;
8-
using Microsoft.OpenApi.Models;
10+
using FluentAssertions.Equivalency;
911
using Microsoft.OpenApi.Extensions;
10-
using SharpYaml.Serialization;
11-
using Xunit;
12+
using Microsoft.OpenApi.Models;
13+
using Microsoft.OpenApi.Models.References;
1214
using Microsoft.OpenApi.Reader;
1315
using Microsoft.OpenApi.Reader.ParseNodes;
1416
using Microsoft.OpenApi.Reader.V3;
15-
using FluentAssertions.Equivalency;
16-
using Microsoft.OpenApi.Models.References;
17-
using System.Threading.Tasks;
18-
using System.Net.Http;
17+
using Microsoft.OpenApi.Tests;
18+
using Microsoft.OpenApi.Writers;
1919
using Microsoft.OpenApi.YamlReader;
20-
using Microsoft.OpenApi.Models.Interfaces;
20+
using SharpYaml.Serialization;
21+
using Xunit;
2122

2223
namespace Microsoft.OpenApi.Readers.Tests.V3Tests
2324
{
@@ -445,5 +446,42 @@ public async Task ParseExternalReferenceSchemaShouldSucceed()
445446

446447
Assert.Equivalent(expectedComponents, components);
447448
}
449+
450+
[Fact]
451+
public async Task SerializeSchemaWithNullableShouldSucceed()
452+
{
453+
// Arrange
454+
var expected = @"type: string
455+
nullable: true";
456+
457+
var path = Path.Combine(SampleFolderPath, "schemaWithNullable.yaml");
458+
459+
// Act
460+
var schema = await OpenApiModelFactory.LoadAsync<OpenApiSchema>(path, OpenApiSpecVersion.OpenApi3_0, new(), SettingsFixture.ReaderSettings);
461+
462+
var writer = new StringWriter();
463+
schema.SerializeAsV3(new OpenApiYamlWriter(writer));
464+
var schemaString = writer.ToString();
465+
466+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), schemaString.MakeLineBreaksEnvironmentNeutral());
467+
}
468+
469+
[Fact]
470+
public async Task SerializeSchemaWithOnlyNullableShouldSucceed()
471+
{
472+
// Arrange
473+
var expected = @"nullable: true";
474+
475+
var path = Path.Combine(SampleFolderPath, "schemaWithOnlyNullable.yaml");
476+
477+
// Act
478+
var schema = await OpenApiModelFactory.LoadAsync<OpenApiSchema>(path, OpenApiSpecVersion.OpenApi3_0, new(), SettingsFixture.ReaderSettings);
479+
480+
var writer = new StringWriter();
481+
schema.SerializeAsV3(new OpenApiYamlWriter(writer));
482+
var schemaString = writer.ToString();
483+
484+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), schemaString.MakeLineBreaksEnvironmentNeutral());
485+
}
448486
}
449487
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
type: string
2+
nullable: true
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nullable: true

0 commit comments

Comments
 (0)