diff --git a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs index b478b8074..d12a24b5f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs @@ -11,6 +11,10 @@ namespace Microsoft.OpenApi /// public class OpenApiEncoding : IOpenApiSerializable, IOpenApiExtensible { + /// + /// Explode backing variable + /// + private bool? _explode; /// /// The Content-Type for encoding a specific property. /// The value can be a specific media type (e.g. application/json), @@ -35,7 +39,11 @@ public class OpenApiEncoding : IOpenApiSerializable, IOpenApiExtensible /// For all other styles, the default value is false. /// This property SHALL be ignored if the request body media type is not application/x-www-form-urlencoded. /// - public bool? Explode { get; set; } + public bool? Explode + { + get => _explode ?? Style == ParameterStyle.Form; + set => _explode = value; + } /// /// Determines whether the parameter value SHOULD allow reserved characters, @@ -63,7 +71,7 @@ public OpenApiEncoding(OpenApiEncoding encoding) ContentType = encoding?.ContentType ?? ContentType; Headers = encoding?.Headers != null ? new Dictionary(encoding.Headers) : null; Style = encoding?.Style ?? Style; - Explode = encoding?.Explode ?? Explode; + Explode = encoding?._explode; AllowReserved = encoding?.AllowReserved ?? AllowReserved; Extensions = encoding?.Extensions != null ? new Dictionary(encoding.Extensions) : null; } @@ -106,7 +114,10 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version writer.WriteProperty(OpenApiConstants.Style, Style?.GetDisplayName()); // explode - writer.WriteProperty(OpenApiConstants.Explode, Explode, false); + if (_explode.HasValue) + { + writer.WriteProperty(OpenApiConstants.Explode, Explode); + } // allowReserved writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiEncodingTests.cs index 0d57b6ee7..81d6426ad 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiEncodingTests.cs @@ -76,5 +76,55 @@ public async Task SerializeAdvanceEncodingAsV3YamlWorks() expected = expected.MakeLineBreaksEnvironmentNeutral(); Assert.Equal(expected, actual); } + + [Theory] + [InlineData(ParameterStyle.Form, true)] + [InlineData(ParameterStyle.SpaceDelimited, false)] + [InlineData(null, false)] + public void WhenStyleIsFormTheDefaultValueOfExplodeShouldBeTrueOtherwiseFalse(ParameterStyle? style, bool expectedExplode) + { + // Arrange + var parameter = new OpenApiEncoding + { + Style = style + }; + + // Act & Assert + Assert.Equal(parameter.Explode, expectedExplode); + } + + [Theory] + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(null, false)] + public async Task WhenExplodeIsSetOutputShouldHaveExplode(bool? expectedExplode, bool hasExplode) + { + // Arrange + OpenApiEncoding parameter = new() + { + ContentType = "multipart/form-data", + Style = ParameterStyle.Form, + Explode = expectedExplode, + }; + + var expected = + $""" + contentType: multipart/form-data + style: form + """; + + if (hasExplode) + { + expected = expected + $"\nexplode: {expectedExplode.ToString().ToLower()}"; + } + + // Act + var actual = await parameter.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0); + + // Assert + actual = actual.MakeLineBreaksEnvironmentNeutral(); + expected = expected.MakeLineBreaksEnvironmentNeutral(); + Assert.Equal(actual, expected); + } } }