From f63443f98f5b4e77de632c85c7cd367395b30ba2 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 2 Aug 2024 18:42:37 +0300 Subject: [PATCH 1/7] Serialize example values with empty arrays for responses --- .../Models/OpenApiMediaType.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 4751c4b28..7e090dfa6 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -76,7 +77,7 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, e) => w.WriteAny(e)); // examples - writer.WriteOptionalMap(OpenApiConstants.Examples, Examples, (w, e) => e.SerializeAsV3(w)); + SerializeExamples(writer, Examples); // encoding writer.WriteOptionalMap(OpenApiConstants.Encoding, Encoding, (w, e) => e.SerializeAsV3(w)); @@ -94,5 +95,36 @@ public void SerializeAsV2(IOpenApiWriter writer) { // Media type does not exist in V2. } + + private void SerializeExamples(IOpenApiWriter writer, IDictionary examples) + { + /* Special case for writing out empty arrays as valid response examples + * Check if there is any example with an empty array as its value + * */ + var hasEmptyArray = examples.Values.Any(example => + example.Value is OpenApiArray arr && arr.Count == 0 + ); + + if (hasEmptyArray) + { + writer.WritePropertyName(OpenApiConstants.Examples); + writer.WriteStartObject(); + foreach (var kvp in examples) + { + if (kvp.Value.Value is OpenApiArray arr && arr.Count == 0) + { + writer.WritePropertyName(kvp.Key); + writer.WriteStartObject(); + writer.WriteRequiredObject(OpenApiConstants.Value, kvp.Value.Value, (w, v) => w.WriteAny(v)); + writer.WriteEndObject(); + } + } + writer.WriteEndObject(); + } + else + { + writer.WriteOptionalMap(OpenApiConstants.Examples, examples, (w, e) => e.SerializeAsV3(w)); + } + } } } From 0b63d77c6e8deb09c12cecd8493584106f49cb39 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 2 Aug 2024 18:43:56 +0300 Subject: [PATCH 2/7] Add unit test to validate --- .../V3Tests/OpenApiMediaTypeTests.cs | 40 +++++++++++++++++++ .../examplesWithEmptyArray.json | 18 +++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiMediaType/examplesWithEmptyArray.json diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs index 8e3a6c864..266809561 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs @@ -4,9 +4,11 @@ using System.IO; using FluentAssertions; using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Readers.ParseNodes; using Microsoft.OpenApi.Readers.V3; +using Microsoft.OpenApi.Tests; using Xunit; namespace Microsoft.OpenApi.Readers.Tests.V3Tests @@ -77,5 +79,43 @@ public void ParseMediaTypeWithExamplesShouldSucceed() } }); } + + [Fact] + public void ParseMediaTypeWithEmptyArrayInExamplesWorks() + { + // Arrange + var expected = @"{ + ""schema"": { + ""type"": ""array"", + ""items"": { + ""type"": ""object"", + ""properties"": { + ""id"": { + ""type"": ""string"" + } + } + } + }, + ""examples"": { + ""Success response - no results"": { + ""value"": [ ] + } + } +} +"; + MapNode node; + using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "examplesWithEmptyArray.json"))) + { + node = TestHelper.CreateYamlMapNode(stream); + } + + // Act + var mediaType = OpenApiV3Deserializer.LoadMediaType(node); + var serialized = mediaType.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); + + // Assert + serialized.MakeLineBreaksEnvironmentNeutral() + .Should().BeEquivalentTo(expected.MakeLineBreaksEnvironmentNeutral()); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiMediaType/examplesWithEmptyArray.json b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiMediaType/examplesWithEmptyArray.json new file mode 100644 index 000000000..0d13dcaf2 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiMediaType/examplesWithEmptyArray.json @@ -0,0 +1,18 @@ +{ + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + } + }, + "examples": { + "Success response - no results": { + "value": [] + } + } +} \ No newline at end of file From 91f83f80bb63653ae9eff2f840553cd919aea88b Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 2 Aug 2024 18:48:39 +0300 Subject: [PATCH 3/7] Update comment --- src/Microsoft.OpenApi/Models/OpenApiMediaType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 7e090dfa6..609ea5ccd 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -99,7 +99,7 @@ public void SerializeAsV2(IOpenApiWriter writer) private void SerializeExamples(IOpenApiWriter writer, IDictionary examples) { /* Special case for writing out empty arrays as valid response examples - * Check if there is any example with an empty array as its value + * Check if there is any example with an empty array as its value and set the flag `hasEmptyArray` to true * */ var hasEmptyArray = examples.Values.Any(example => example.Value is OpenApiArray arr && arr.Count == 0 From 28142d5cb4319e6b02a37a56691c150e92ae8957 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 2 Aug 2024 19:12:53 +0300 Subject: [PATCH 4/7] Simplify by using .Where() for sequence filtering --- src/Microsoft.OpenApi/Models/OpenApiMediaType.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 609ea5ccd..553e87d09 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -109,15 +109,12 @@ private void SerializeExamples(IOpenApiWriter writer, IDictionary kvp.Value.Value is OpenApiArray arr && arr.Count == 0)) { - if (kvp.Value.Value is OpenApiArray arr && arr.Count == 0) - { - writer.WritePropertyName(kvp.Key); - writer.WriteStartObject(); - writer.WriteRequiredObject(OpenApiConstants.Value, kvp.Value.Value, (w, v) => w.WriteAny(v)); - writer.WriteEndObject(); - } + writer.WritePropertyName(kvp.Key); + writer.WriteStartObject(); + writer.WriteRequiredObject(OpenApiConstants.Value, kvp.Value.Value, (w, v) => w.WriteAny(v)); + writer.WriteEndObject(); } writer.WriteEndObject(); } From 38ba98ec054e60de02ee4fb02406e9cefac7b986 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 5 Aug 2024 11:07:44 +0300 Subject: [PATCH 5/7] Update src/Microsoft.OpenApi/Models/OpenApiMediaType.cs Co-authored-by: Andrew Omondi --- src/Microsoft.OpenApi/Models/OpenApiMediaType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 553e87d09..1c0a95b5f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -101,7 +101,7 @@ private void SerializeExamples(IOpenApiWriter writer, IDictionary + var hasEmptyArray = examples.Values.Any( static example => example.Value is OpenApiArray arr && arr.Count == 0 ); From 1c199862c3debef1dc93df361d4088f1329ffb34 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 5 Aug 2024 11:07:52 +0300 Subject: [PATCH 6/7] Update src/Microsoft.OpenApi/Models/OpenApiMediaType.cs Co-authored-by: Andrew Omondi --- src/Microsoft.OpenApi/Models/OpenApiMediaType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 1c0a95b5f..c324c9ee8 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -109,7 +109,7 @@ private void SerializeExamples(IOpenApiWriter writer, IDictionary kvp.Value.Value is OpenApiArray arr && arr.Count == 0)) + foreach (var kvp in examples.Where(static kvp => kvp.Value.Value is OpenApiArray arr && arr.Count == 0)) { writer.WritePropertyName(kvp.Key); writer.WriteStartObject(); From 27258e911c93a932b61837c4f4c202e62a544840 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 5 Aug 2024 11:07:59 +0300 Subject: [PATCH 7/7] Update src/Microsoft.OpenApi/Models/OpenApiMediaType.cs Co-authored-by: Andrew Omondi --- src/Microsoft.OpenApi/Models/OpenApiMediaType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index c324c9ee8..3816fb14f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -96,7 +96,7 @@ public void SerializeAsV2(IOpenApiWriter writer) // Media type does not exist in V2. } - private void SerializeExamples(IOpenApiWriter writer, IDictionary examples) + private static void SerializeExamples(IOpenApiWriter writer, IDictionary examples) { /* Special case for writing out empty arrays as valid response examples * Check if there is any example with an empty array as its value and set the flag `hasEmptyArray` to true