diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 8787e7697..797ec2359 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -192,16 +192,17 @@ private static async Task WriteOpenApiAsync(HidiOptions options, string openApiF using var outputStream = options.Output.Create(); using var textWriter = new StreamWriter(outputStream); - var settings = new OpenApiWriterSettings + var settings = new OpenApiJsonWriterSettings { InlineLocalReferences = options.InlineLocal, - InlineExternalReferences = options.InlineExternal + InlineExternalReferences = options.InlineExternal, + Terse = options.TerseOutput }; #pragma warning disable CA1308 IOpenApiWriter writer = openApiFormat.ToLowerInvariant() switch #pragma warning restore CA1308 { - OpenApiConstants.Json => options.TerseOutput ? new(textWriter, settings, options.TerseOutput) : new OpenApiJsonWriter(textWriter, settings, false), + OpenApiConstants.Json => new OpenApiJsonWriter(textWriter, settings), OpenApiConstants.Yaml => new OpenApiYamlWriter(textWriter, settings), _ => throw new ArgumentException("Unknown format"), }; diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs index 1ed0aacab..fdca97797 100755 --- a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs @@ -88,7 +88,8 @@ public static Task SerializeAsync( IOpenApiWriter writer = format.ToLowerInvariant() switch { - OpenApiConstants.Json => new OpenApiJsonWriter(streamWriter, settings, false), + OpenApiConstants.Json when settings is OpenApiJsonWriterSettings jsonSettings => new OpenApiJsonWriter(streamWriter, jsonSettings), + OpenApiConstants.Json => new OpenApiJsonWriter(streamWriter, settings), OpenApiConstants.Yaml => new OpenApiYamlWriter(streamWriter, settings), _ => throw new OpenApiException(string.Format(SRResource.OpenApiFormatNotSupported, format)), }; diff --git a/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs b/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs index feffb3b59..11dda6c59 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; +using System.ComponentModel; using System.IO; namespace Microsoft.OpenApi @@ -14,7 +16,17 @@ public class OpenApiJsonWriter : OpenApiWriterBase /// Initializes a new instance of the class. /// /// The text writer. - public OpenApiJsonWriter(TextWriter textWriter) : base(textWriter, null) + public OpenApiJsonWriter(TextWriter textWriter) : this(textWriter, (OpenApiWriterSettings?)null) + { + // this constructor is kept for binary compatibility + // TODO remove in next major version and make the settings an optional parameter in the other constructor + } + /// + /// Initializes a new instance of the class. + /// + /// Settings for controlling how the OpenAPI document will be written out. + /// The text writer. + public OpenApiJsonWriter(TextWriter textWriter, OpenApiWriterSettings? settings) : base(textWriter, settings ?? new OpenApiJsonWriterSettings()) { } @@ -34,9 +46,13 @@ public OpenApiJsonWriter(TextWriter textWriter, OpenApiJsonWriterSettings settin /// The text writer. /// Settings for controlling how the OpenAPI document will be written out. /// Setting for allowing the JSON emitted to be in terse format. - public OpenApiJsonWriter(TextWriter textWriter, OpenApiWriterSettings? settings, bool terseOutput = false) : base(textWriter, settings) + [Obsolete("Use OpenApiJsonWriter(TextWriter textWriter, OpenApiJsonWriterSettings settings) instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public OpenApiJsonWriter(TextWriter textWriter, OpenApiWriterSettings? settings, bool terseOutput) : base(textWriter, settings) { _produceTerseOutput = terseOutput; + // this constructor is kept for binary compatibility, terse information should be read from the settings to avoid fork APIs. + // TODO remove in next major version } /// diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs index 7d80480d0..e3848ec69 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs @@ -55,10 +55,7 @@ protected OpenApiWriterBase(TextWriter textWriter, OpenApiWriterSettings? settin Writer.NewLine = "\n"; Scopes = new(); - if (settings == null) - { - settings = new(); - } + settings ??= new(); Settings = settings; } diff --git a/test/Microsoft.OpenApi.Tests/Extensions/OpenApiSerializableExtensionsTests.cs b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiSerializableExtensionsTests.cs new file mode 100644 index 000000000..a1e323ebf --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiSerializableExtensionsTests.cs @@ -0,0 +1,93 @@ +using System.IO; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.OpenApi.Tests.Extensions; + +public class OpenApiSerializableExtensionsTests +{ + [Fact] + public async Task UsesTheTerseOutputInformationFromSettingsTrue() + { + var parameter = new OpenApiParameter + { + Name = "param1", + In = ParameterLocation.Query, + Description = "A sample parameter", + Required = false, + Schema = new OpenApiSchema + { + Type = JsonSchemaType.String + } + }; + + var settings = new OpenApiJsonWriterSettings + { + Terse = true + }; + + using var stream = new MemoryStream(); + await parameter.SerializeAsync(stream, OpenApiSpecVersion.OpenApi3_1, OpenApiConstants.Json, settings); + + stream.Position = 0; + using var reader = new StreamReader(stream); + var output = await reader.ReadToEndAsync(); + + Assert.Equal("{\"name\":\"param1\",\"in\":\"query\",\"description\":\"A sample parameter\",\"schema\":{\"type\":\"string\"}}", output); + } + + [Fact] + public async Task UsesTheTerseOutputInformationFromSettingsFalse() + { + var parameter = new OpenApiParameter + { + Name = "param1", + In = ParameterLocation.Query, + Description = "A sample parameter", + Required = false, + Schema = new OpenApiSchema + { + Type = JsonSchemaType.String + } + }; + + var settings = new OpenApiJsonWriterSettings + { + Terse = false + }; + + using var stream = new MemoryStream(); + await parameter.SerializeAsync(stream, OpenApiSpecVersion.OpenApi3_1, OpenApiConstants.Json, settings); + + stream.Position = 0; + using var reader = new StreamReader(stream); + var output = await reader.ReadToEndAsync(); + + Assert.Equal("{\n \"name\": \"param1\",\n \"in\": \"query\",\n \"description\": \"A sample parameter\",\n \"schema\": {\n \"type\": \"string\"\n }\n}", output); + } + + [Fact] + public async Task UsesTheTerseOutputInformationFromSettingsNoSettings() + { + var parameter = new OpenApiParameter + { + Name = "param1", + In = ParameterLocation.Query, + Description = "A sample parameter", + Required = false, + Schema = new OpenApiSchema + { + Type = JsonSchemaType.String + } + }; + + using var stream = new MemoryStream(); + await parameter.SerializeAsync(stream, OpenApiSpecVersion.OpenApi3_1, OpenApiConstants.Json, null); + + stream.Position = 0; + using var reader = new StreamReader(stream); + var output = await reader.ReadToEndAsync(); + + Assert.Equal("{\n \"name\": \"param1\",\n \"in\": \"query\",\n \"description\": \"A sample parameter\",\n \"schema\": {\n \"type\": \"string\"\n }\n}", output); + } +} diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 408ddb15e..87276efce 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -795,7 +795,10 @@ namespace Microsoft.OpenApi { public OpenApiJsonWriter(System.IO.TextWriter textWriter) { } public OpenApiJsonWriter(System.IO.TextWriter textWriter, Microsoft.OpenApi.OpenApiJsonWriterSettings settings) { } - public OpenApiJsonWriter(System.IO.TextWriter textWriter, Microsoft.OpenApi.OpenApiWriterSettings? settings, bool terseOutput = false) { } + public OpenApiJsonWriter(System.IO.TextWriter textWriter, Microsoft.OpenApi.OpenApiWriterSettings? settings) { } + [System.Obsolete("Use OpenApiJsonWriter(TextWriter textWriter, OpenApiJsonWriterSettings settings) " + + "instead.")] + public OpenApiJsonWriter(System.IO.TextWriter textWriter, Microsoft.OpenApi.OpenApiWriterSettings? settings, bool terseOutput) { } protected override int BaseIndentation { get; } public override void WriteEndArray() { } public override void WriteEndObject() { }