From 4a6b81683e33736e1280f02d940e62540d390db8 Mon Sep 17 00:00:00 2001 From: Adrian Obando Date: Tue, 3 Jun 2025 13:15:37 -0600 Subject: [PATCH 1/4] feat: serialize const prop from 3.1 schemas as single enum for prior versions Refs: #2335 --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 10 ++++- .../Models/OpenApiSchemaTests.cs | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 17ba10ada..51265a7ef 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -437,7 +437,10 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version }); // enum - writer.WriteOptionalCollection(OpenApiConstants.Enum, Enum, (nodeWriter, s) => nodeWriter.WriteAny(s)); + var enumValue = !string.IsNullOrEmpty(Const) && version != OpenApiSpecVersion.OpenApi3_1 + ? new List { JsonValue.Create(Const)! } + : Enum; + writer.WriteOptionalCollection(OpenApiConstants.Enum, enumValue, (nodeWriter, s) => nodeWriter.WriteAny(s)); // type SerializeTypeProperty(writer, version); @@ -687,7 +690,10 @@ private void SerializeAsV2( }); // enum - writer.WriteOptionalCollection(OpenApiConstants.Enum, Enum, (w, s) => w.WriteAny(s)); + var enumValue = !string.IsNullOrEmpty(Const) + ? new List { JsonValue.Create(Const)! } + : Enum; + writer.WriteOptionalCollection(OpenApiConstants.Enum, enumValue, (nodeWriter, s) => nodeWriter.WriteAny(s)); // items writer.WriteOptionalObject(OpenApiConstants.Items, Items, (w, s) => s.SerializeAsV2(w)); diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index ef5ca3d59..4212317f1 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -643,6 +643,44 @@ public async Task WriteAsItemsPropertiesDoesNotWriteNull() """; Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } + [Fact] + public async Task SerializeConstAsEnumV30() + { + // Arrange + var schema = new OpenApiSchema + { + Type = JsonSchemaType.String, + Const = "foo" + }; + + + // Act + var actual = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); + + // Assert + var v3Node = JsonNode.Parse(actual); + Assert.True(v3Node!["enum"] is JsonArray singleEnum && singleEnum.Count == 1 && singleEnum[0]?.ToString() == "foo"); + Assert.False(v3Node.AsObject().ContainsKey("const")); + } + + [Fact] + public async Task SerializeConstAsEnumV20() + { + // Arrange + var schema = new OpenApiSchema + { + Type = JsonSchemaType.String, + Const = "foo" + }; + + // Act + var actual = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); + + // Assert + var v2Node = JsonNode.Parse(actual); + Assert.True(v2Node!["enum"] is JsonArray singleEnum && singleEnum.Count == 1 && singleEnum[0]?.ToString() == "foo"); + Assert.False(v2Node.AsObject().ContainsKey("const")); + } internal class SchemaVisitor : OpenApiVisitorBase From 0f540aea10a1429b3d8344cfd7ff31c31846aa69 Mon Sep 17 00:00:00 2001 From: Adrian Date: Wed, 4 Jun 2025 11:12:19 -0600 Subject: [PATCH 2/4] Update src/Microsoft.OpenApi/Models/OpenApiSchema.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 51265a7ef..307e90599 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -437,7 +437,7 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version }); // enum - var enumValue = !string.IsNullOrEmpty(Const) && version != OpenApiSpecVersion.OpenApi3_1 + var enumValue = !string.IsNullOrEmpty(Const) && version < OpenApiSpecVersion.OpenApi3_1 ? new List { JsonValue.Create(Const)! } : Enum; writer.WriteOptionalCollection(OpenApiConstants.Enum, enumValue, (nodeWriter, s) => nodeWriter.WriteAny(s)); From 5267b645535f4a3e03125d225cfdefa5e4686966 Mon Sep 17 00:00:00 2001 From: Adrian Obando Date: Wed, 4 Jun 2025 11:51:53 -0600 Subject: [PATCH 3/4] chore: code review changes --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 6 ++++-- test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 307e90599..d00d8c8c5 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -437,7 +437,9 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version }); // enum - var enumValue = !string.IsNullOrEmpty(Const) && version < OpenApiSpecVersion.OpenApi3_1 + var enumValue = (Enum == null || Enum.Count == 0) + && !string.IsNullOrEmpty(Const) + && version < OpenApiSpecVersion.OpenApi3_1 ? new List { JsonValue.Create(Const)! } : Enum; writer.WriteOptionalCollection(OpenApiConstants.Enum, enumValue, (nodeWriter, s) => nodeWriter.WriteAny(s)); @@ -690,7 +692,7 @@ private void SerializeAsV2( }); // enum - var enumValue = !string.IsNullOrEmpty(Const) + var enumValue = (Enum == null || Enum.Count == 0) && !string.IsNullOrEmpty(Const) ? new List { JsonValue.Create(Const)! } : Enum; writer.WriteOptionalCollection(OpenApiConstants.Enum, enumValue, (nodeWriter, s) => nodeWriter.WriteAny(s)); diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 4212317f1..87dc85ced 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -659,7 +659,8 @@ public async Task SerializeConstAsEnumV30() // Assert var v3Node = JsonNode.Parse(actual); - Assert.True(v3Node!["enum"] is JsonArray singleEnum && singleEnum.Count == 1 && singleEnum[0]?.ToString() == "foo"); + Assert.NotNull(v3Node); + Assert.True(v3Node["enum"] is JsonArray singleEnum && singleEnum.Count == 1 && singleEnum[0]?.ToString() == "foo"); Assert.False(v3Node.AsObject().ContainsKey("const")); } @@ -678,7 +679,8 @@ public async Task SerializeConstAsEnumV20() // Assert var v2Node = JsonNode.Parse(actual); - Assert.True(v2Node!["enum"] is JsonArray singleEnum && singleEnum.Count == 1 && singleEnum[0]?.ToString() == "foo"); + Assert.NotNull(v2Node); + Assert.True(v2Node["enum"] is JsonArray singleEnum && singleEnum.Count == 1 && singleEnum[0]?.ToString() == "foo"); Assert.False(v2Node.AsObject().ContainsKey("const")); } From 3a8f7e229316c248bb26fc63cd1786d255a05bb4 Mon Sep 17 00:00:00 2001 From: Adrian Obando Date: Wed, 4 Jun 2025 12:02:19 -0600 Subject: [PATCH 4/4] chore: adding nit suggested --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index d00d8c8c5..db3064b00 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -437,7 +437,7 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version }); // enum - var enumValue = (Enum == null || Enum.Count == 0) + var enumValue = Enum is not { Count: > 0 } && !string.IsNullOrEmpty(Const) && version < OpenApiSpecVersion.OpenApi3_1 ? new List { JsonValue.Create(Const)! } @@ -692,7 +692,7 @@ private void SerializeAsV2( }); // enum - var enumValue = (Enum == null || Enum.Count == 0) && !string.IsNullOrEmpty(Const) + var enumValue = Enum is not { Count: > 0 } && !string.IsNullOrEmpty(Const) ? new List { JsonValue.Create(Const)! } : Enum; writer.WriteOptionalCollection(OpenApiConstants.Enum, enumValue, (nodeWriter, s) => nodeWriter.WriteAny(s));