Skip to content
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Globalization;
Expand All @@ -21,12 +21,31 @@ public static class OpenApiSerializableExtensions
/// <param name="stream">The output stream.</param>
/// <param name="specVersion">The Open API specification version.</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0027 // The settings overload below has the same parameter count but different types; no ambiguity exists.
public static Task SerializeAsJsonAsync<T>(this T element, Stream stream, OpenApiSpecVersion specVersion, CancellationToken cancellationToken = default)
#pragma warning restore RS0027
Comment thread
baywet marked this conversation as resolved.
where T : IOpenApiSerializable
{
return element.SerializeAsync(stream, specVersion, OpenApiConstants.Json, cancellationToken);
}

/// <summary>
/// Serialize the <see cref="IOpenApiSerializable"/> to the Open API document (JSON) using the given stream, specification version and settings.
/// </summary>
/// <typeparam name="T">the <see cref="IOpenApiSerializable"/></typeparam>
/// <param name="element">The Open API element.</param>
/// <param name="stream">The output stream.</param>
/// <param name="specVersion">The Open API specification version.</param>
/// <param name="settings">Settings controlling JSON output, including <see cref="OpenApiJsonWriterSettings.Terse"/> for compact formatting.</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0026 // Intentional overload alongside the CancellationToken-only variant; types are unambiguous.
public static Task SerializeAsJsonAsync<T>(this T element, Stream stream, OpenApiSpecVersion specVersion, OpenApiJsonWriterSettings settings, CancellationToken cancellationToken = default)
#pragma warning restore RS0026
where T : IOpenApiSerializable
{
return element.SerializeAsync(stream, specVersion, OpenApiConstants.Json, settings, cancellationToken);
}

/// <summary>
/// Serializes the <see cref="IOpenApiSerializable"/> to the Open API document (YAML) using the given stream and specification version.
/// </summary>
Expand All @@ -51,12 +70,14 @@ public static Task SerializeAsYamlAsync<T>(this T element, Stream stream, OpenAp
/// <param name="specVersion">The Open API specification version.</param>
/// <param name="format">The output format (JSON or YAML).</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0027 // The settings overload below has the same parameter count but different types; no ambiguity exists.
public static Task SerializeAsync<T>(
this T element,
Stream stream,
OpenApiSpecVersion specVersion,
string format,
CancellationToken cancellationToken = default)
#pragma warning restore RS0027
where T : IOpenApiSerializable
{
return element.SerializeAsync(stream, specVersion, format, null, cancellationToken);
Expand Down Expand Up @@ -104,7 +125,9 @@ public static Task SerializeAsync<T>(
/// <param name="writer">The output writer.</param>
/// <param name="specVersion">Version of the specification the output should conform to</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0027 // The settings-bearing SerializeAsync overloads below have the same parameter count but different types; no ambiguity exists.
public static Task SerializeAsync<T>(this T element, IOpenApiWriter writer, OpenApiSpecVersion specVersion, CancellationToken cancellationToken = default)
#pragma warning restore RS0027
where T : IOpenApiSerializable
Comment thread
baywet marked this conversation as resolved.
{
Utils.CheckArgumentNull(element);
Expand Down Expand Up @@ -142,15 +165,37 @@ public static Task SerializeAsync<T>(this T element, IOpenApiWriter writer, Open
/// <param name="element">The Open API element.</param>
/// <param name="specVersion">The Open API specification version.</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0027 // The settings overload below has the same parameter count but different types; no ambiguity exists.
public static Task<string> SerializeAsJsonAsync<T>(
this T element,
OpenApiSpecVersion specVersion,
CancellationToken cancellationToken = default)
#pragma warning restore RS0027
where T : IOpenApiSerializable
{
return element.SerializeAsync(specVersion, OpenApiConstants.Json, cancellationToken);
}

/// <summary>
/// Serializes the <see cref="IOpenApiSerializable"/> to the Open API document as a string in JSON format using the given settings.
/// </summary>
/// <typeparam name="T">the <see cref="IOpenApiSerializable"/></typeparam>
/// <param name="element">The Open API element.</param>
/// <param name="specVersion">The Open API specification version.</param>
/// <param name="settings">Settings controlling JSON output, including <see cref="OpenApiJsonWriterSettings.Terse"/> for compact formatting.</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0026 // Intentional overload alongside the CancellationToken-only variant; types are unambiguous.
public static Task<string> SerializeAsJsonAsync<T>(
this T element,
OpenApiSpecVersion specVersion,
OpenApiJsonWriterSettings settings,
CancellationToken cancellationToken = default)
#pragma warning restore RS0026
where T : IOpenApiSerializable
{
return element.SerializeAsync(specVersion, OpenApiConstants.Json, settings, cancellationToken);
}

/// <summary>
/// Serializes the <see cref="IOpenApiSerializable"/> to the Open API document as a string in YAML format.
/// </summary>
Expand All @@ -175,11 +220,13 @@ public static Task<string> SerializeAsYamlAsync<T>(
/// <param name="specVersion">The Open API specification version.</param>
/// <param name="format">Open API document format.</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0027 // The settings overload below has the same parameter count but different types; no ambiguity exists.
public static async Task<string> SerializeAsync<T>(
this T element,
OpenApiSpecVersion specVersion,
string format,
CancellationToken cancellationToken = default)
#pragma warning restore RS0027
where T : IOpenApiSerializable
{
Utils.CheckArgumentNull(element);
Expand All @@ -195,5 +242,38 @@ public static async Task<string> SerializeAsync<T>(
return await streamReader.ReadToEndAsync().ConfigureAwait(false);
#endif
}

/// <summary>
/// Serializes the <see cref="IOpenApiSerializable"/> to the Open API document as a string in the given format using the given settings.
/// </summary>
/// <typeparam name="T">the <see cref="IOpenApiSerializable"/></typeparam>
/// <param name="element">The Open API element.</param>
/// <param name="specVersion">The Open API specification version.</param>
/// <param name="format">Open API document format.</param>
/// <param name="settings">Provide configuration settings for controlling writing output.</param>
/// <param name="cancellationToken">The cancellation token.</param>
#pragma warning disable RS0026 // Intentional overload alongside the CancellationToken-only variant; types are unambiguous.
public static async Task<string> SerializeAsync<T>(
this T element,
OpenApiSpecVersion specVersion,
string format,
OpenApiWriterSettings? settings,
CancellationToken cancellationToken = default)
#pragma warning restore RS0026
where T : IOpenApiSerializable
{
Utils.CheckArgumentNull(element);

using var stream = new MemoryStream();
await element.SerializeAsync(stream, specVersion, format, settings, cancellationToken).ConfigureAwait(false);
stream.Position = 0;

using var streamReader = new StreamReader(stream);
#if NET7_0_OR_GREATER
return await streamReader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
#else
return await streamReader.ReadToEndAsync().ConfigureAwait(false);
#endif
}
}
}
5 changes: 5 additions & 0 deletions src/Microsoft.OpenApi/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
#nullable enable
const Microsoft.OpenApi.OpenApiConstants.JsonSchemaExamplesExtension = "x-jsonschema-examples" -> string!
const Microsoft.OpenApi.OpenApiConstants.OaiLicenseIdentifier = "x-oai-license-identifier" -> string!
Comment thread
Mahdigln marked this conversation as resolved.
Outdated
static Microsoft.OpenApi.OpenApiSerializableExtensions.SerializeAsJsonAsync<T>(this T element, Microsoft.OpenApi.OpenApiSpecVersion specVersion, Microsoft.OpenApi.OpenApiJsonWriterSettings! settings, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<string!>!
static Microsoft.OpenApi.OpenApiSerializableExtensions.SerializeAsJsonAsync<T>(this T element, System.IO.Stream! stream, Microsoft.OpenApi.OpenApiSpecVersion specVersion, Microsoft.OpenApi.OpenApiJsonWriterSettings! settings, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
static Microsoft.OpenApi.OpenApiSerializableExtensions.SerializeAsync<T>(this T element, Microsoft.OpenApi.OpenApiSpecVersion specVersion, string! format, Microsoft.OpenApi.OpenApiWriterSettings? settings, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<string!>!
Comment thread
baywet marked this conversation as resolved.
Comment thread
baywet marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
Comment thread
baywet marked this conversation as resolved.

Expand Down Expand Up @@ -90,4 +91,60 @@ public async Task UsesTheTerseOutputInformationFromSettingsNoSettings()

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 SerializeAsJsonAsync_WithTerseSettings_WritesToStream()
{
var parameter = new OpenApiParameter
{
Name = "param1",
In = ParameterLocation.Query,
Schema = new OpenApiSchema { Type = JsonSchemaType.String }
};

var settings = new OpenApiJsonWriterSettings { Terse = true };

using var stream = new MemoryStream();
await parameter.SerializeAsJsonAsync(stream, OpenApiSpecVersion.OpenApi3_1, settings, TestContext.Current.CancellationToken);

stream.Position = 0;
using var reader = new StreamReader(stream);
var output = await reader.ReadToEndAsync();

Assert.Equal("{\"name\":\"param1\",\"in\":\"query\",\"schema\":{\"type\":\"string\"}}", output);
}

[Fact]
public async Task SerializeAsJsonAsync_WithTerseSettings_ReturnsCompactString()
{
var parameter = new OpenApiParameter
{
Name = "param1",
In = ParameterLocation.Query,
Schema = new OpenApiSchema { Type = JsonSchemaType.String }
};

var settings = new OpenApiJsonWriterSettings { Terse = true };

var output = await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_1, settings, TestContext.Current.CancellationToken);

Assert.Equal("{\"name\":\"param1\",\"in\":\"query\",\"schema\":{\"type\":\"string\"}}", output);
}

[Fact]
public async Task SerializeAsync_WithSettings_ReturnsFormattedString()
{
var parameter = new OpenApiParameter
{
Name = "param1",
In = ParameterLocation.Query,
Schema = new OpenApiSchema { Type = JsonSchemaType.String }
};

var settings = new OpenApiJsonWriterSettings { Terse = false };

var output = await parameter.SerializeAsync(OpenApiSpecVersion.OpenApi3_1, OpenApiConstants.Json, settings, TestContext.Current.CancellationToken);

Assert.Equal("{\n \"name\": \"param1\",\n \"in\": \"query\",\n \"schema\": {\n \"type\": \"string\"\n }\n}", output);
}
}