diff --git a/src/Microsoft.OpenApi.Readers/ParsingContext.cs b/src/Microsoft.OpenApi.Readers/ParsingContext.cs index 905bfff98..c6c14d215 100644 --- a/src/Microsoft.OpenApi.Readers/ParsingContext.cs +++ b/src/Microsoft.OpenApi.Readers/ParsingContext.cs @@ -69,7 +69,7 @@ internal OpenApiDocument Parse(YamlDocument yamlDocument) case string version when version.is3_0() || version.is3_1(): VersionService = new OpenApiV3VersionService(Diagnostic); doc = VersionService.LoadDocument(RootNode); - this.Diagnostic.SpecificationVersion = OpenApiSpecVersion.OpenApi3_0; + this.Diagnostic.SpecificationVersion = version.is3_1() ? OpenApiSpecVersion.OpenApi3_1 : OpenApiSpecVersion.OpenApi3_0; ValidateRequiredFields(doc, version); break; diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiDocumentDeserializer.cs index cdf720237..858f13f0d 100644 --- a/src/Microsoft.OpenApi.Readers/V3/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V3/OpenApiDocumentDeserializer.cs @@ -21,6 +21,7 @@ internal static partial class OpenApiV3Deserializer } /* Version is valid field but we already parsed it */ }, {"info", (o, n) => o.Info = LoadInfo(n)}, + {"jsonSchemaDialect", (o, n) => o.JsonSchemaDialect = n.GetScalarValue() }, {"servers", (o, n) => o.Servers = n.CreateList(LoadServer)}, {"paths", (o, n) => o.Paths = LoadPaths(n)}, {"webhooks", (o, n) => o.Webhooks = LoadPaths(n)}, diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs index f60c5483b..6489c0fc0 100755 --- a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs @@ -117,6 +117,10 @@ public static void Serialize(this T element, IOpenApiWriter writer, OpenApiSp switch (specVersion) { + case OpenApiSpecVersion.OpenApi3_1: + element.SerializeAsV31(writer); + break; + case OpenApiSpecVersion.OpenApi3_0: element.SerializeAsV3(writer); break; diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs index c790e1fda..e4d1224ab 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs @@ -3,6 +3,7 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Interfaces { @@ -21,7 +22,12 @@ public interface IOpenApiReferenceable : IOpenApiSerializable /// Reference object. /// OpenApiReference Reference { get; set; } - + + /// + /// Serialize to OpenAPI V31 document without using reference. + /// + void SerializeAsV31WithoutReference(IOpenApiWriter writer); + /// /// Serialize to OpenAPI V3 document without using reference. /// diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs index 582bd49cd..8dbe514f5 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs @@ -10,6 +10,12 @@ namespace Microsoft.OpenApi.Interfaces /// public interface IOpenApiSerializable : IOpenApiElement { + /// + /// Serialize OpenAPI element into v3.1 + /// + /// + void SerializeAsV31(IOpenApiWriter writer); + /// /// Serialize Open API element to v3.0. /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs index 2dcae12d1..09f1b6256 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Expressions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -75,16 +76,38 @@ public void AddPathItem(RuntimeExpression expression, OpenApiPathItem pathItem) PathItems.Add(expression, pathItem); } - + + /// + /// Serialize to Open Api v3.1 + /// + /// + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, referenceElement) => referenceElement.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, referenceElement) => referenceElement.SerializeAsV3WithoutReference(writer)); + } + + /// + /// Serialize + /// + /// + /// + /// + private void SerializeInternal(IOpenApiWriter writer, + Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -92,7 +115,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -100,7 +123,7 @@ public void SerializeAsV3(IOpenApiWriter writer) target = GetEffective(Reference.HostDocument); } } - target.SerializeAsV3WithoutReference(writer); + action(writer, target); } /// @@ -120,24 +143,38 @@ public OpenApiCallback GetEffective(OpenApiDocument doc) } } + /// + /// Serialize to OpenAPI V31 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + (writer, element) => element.SerializeAsV31(writer)); + } /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); // path items foreach (var item in PathItems) { - writer.WriteRequiredObject(item.Key.Expression, item.Value, (w, p) => p.SerializeAsV3(w)); + writer.WriteRequiredObject(item.Key.Expression, item.Value, callback); } // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); - + writer.WriteExtensions(Extensions, version); + writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index 87c7fdea7..550248210 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -95,39 +97,72 @@ public OpenApiComponents(OpenApiComponents components) } /// - /// Serialize to Open Api v3.0. + /// Serialize to Open API v3.1. /// - public void SerializeAsV3(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); // If references have been inlined we don't need the to render the components section // however if they have cycles, then we will need a component rendered if (writer.GetSettings().InlineLocalReferences) { - var loops = writer.GetSettings().LoopDetector.Loops; - writer.WriteStartObject(); - if (loops.TryGetValue(typeof(OpenApiSchema), out List schemas)) + RenderComponents(writer); + return; + } + + writer.WriteStartObject(); + + // pathItems - only present in v3.1 + writer.WriteOptionalMap( + OpenApiConstants.PathItems, + PathItems, + (w, key, component) => + { + if (component.Reference != null && + component.Reference.Type == ReferenceType.Schema && + component.Reference.Id == key) { - var openApiSchemas = schemas.Cast().Distinct().ToList() - .ToDictionary(k => k.Reference.Id); - - writer.WriteOptionalMap( - OpenApiConstants.Schemas, - Schemas, - (w, key, component) => { - component.SerializeAsV3WithoutReference(w); - }); + component.SerializeAsV31WithoutReference(w); } - writer.WriteEndObject(); - return; + else + { + component.SerializeAsV31(w); + } + }); + + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer), + (writer, referenceElement) => referenceElement.SerializeAsV31WithoutReference(writer)); + } + + /// + /// Serialize to v3.0 + /// + /// + public void SerializeAsV3(IOpenApiWriter writer) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); + + // If references have been inlined we don't need the to render the components section + // however if they have cycles, then we will need a component rendered + if (writer.GetSettings().InlineLocalReferences) + { + RenderComponents(writer); + return; } writer.WriteStartObject(); - + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer), + (writer, referenceElement) => referenceElement.SerializeAsV3WithoutReference(writer)); + } + + /// + /// Serialize . + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback, Action action) + { // Serialize each referenceable object as full object without reference if the reference in the object points to itself. // If the reference exists but points to other objects, the object is serialized to just that reference. @@ -139,13 +174,13 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.Schema && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -157,13 +192,13 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.Response && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -175,13 +210,13 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.Parameter && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -193,13 +228,13 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.Example && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(writer, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -210,14 +245,15 @@ public void SerializeAsV3(IOpenApiWriter writer) (w, key, component) => { if (component.Reference != null && - component.Reference.Type == ReferenceType.RequestBody && - component.Reference.Id == key) + component.Reference.Type == ReferenceType.RequestBody && + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) + { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -229,13 +265,13 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.Header && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -247,13 +283,13 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.SecurityScheme && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -265,13 +301,13 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.Link && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); @@ -283,40 +319,38 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (component.Reference != null && component.Reference.Type == ReferenceType.Callback && - component.Reference.Id == key) - { - component.SerializeAsV3WithoutReference(w); - } - else - { - component.SerializeAsV3(w); - } - }); - - // pathItems - writer.WriteOptionalMap( - OpenApiConstants.PathItems, - PathItems, - (w, key, component) => - { - if (component.Reference != null && - component.Reference.Type == ReferenceType.Schema && - component.Reference.Id == key) + string.Equals(component.Reference.Id, key, StringComparison.OrdinalIgnoreCase)) { - component.SerializeAsV3WithoutReference(w); + action(w, component); } else { - component.SerializeAsV3(w); + callback(w, component); } }); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); - + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } + private void RenderComponents(IOpenApiWriter writer) + { + var loops = writer.GetSettings().LoopDetector.Loops; + writer.WriteStartObject(); + if (loops.TryGetValue(typeof(OpenApiSchema), out List schemas)) + { + + writer.WriteOptionalMap( + OpenApiConstants.Schemas, + Schemas, + static (w, key, component) => { + component.SerializeAsV31WithoutReference(w); + }); + } + writer.WriteEndObject(); + } + /// /// Serialize to Open Api v2.0. /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs index f3b925eeb..235240e33 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -19,6 +19,11 @@ public static class OpenApiConstants /// Field: Info /// public const string Info = "info"; + + /// + /// Field: JsonSchemaDialect + /// + public const string JsonSchemaDialect = "jsonSchemaDialect"; /// /// Field: Webhooks diff --git a/src/Microsoft.OpenApi/Models/OpenApiContact.cs b/src/Microsoft.OpenApi/Models/OpenApiContact.cs index 352697bf2..5feb85b6c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiContact.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiContact.cs @@ -51,6 +51,15 @@ public OpenApiContact(OpenApiContact contact) Extensions = contact?.Extensions != null ? new Dictionary(contact.Extensions) : null; } + /// + /// Serialize to Open Api v3.1 + /// + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + WriteInternal(writer, OpenApiSpecVersion.OpenApi3_1); + } + /// /// Serialize to Open Api v3.0 /// @@ -69,10 +78,7 @@ public void SerializeAsV2(IOpenApiWriter writer) private void WriteInternal(IOpenApiWriter writer, OpenApiSpecVersion specVersion) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs index 9ae7f0e6a..3a2434d10 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs @@ -36,15 +36,30 @@ public OpenApiDiscriminator(OpenApiDiscriminator discriminator) Mapping = discriminator?.Mapping != null ? new Dictionary(discriminator.Mapping) : null; } + /// + /// Serialize to Open Api v3.1 + /// + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer); + } + + /// + /// Serialize to Open Api v3.0 + /// + /// + private void SerializeInternal(IOpenApiWriter writer) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); @@ -53,8 +68,6 @@ public void SerializeAsV3(IOpenApiWriter writer) // mapping writer.WriteOptionalMap(OpenApiConstants.Mapping, Mapping, (w, s) => w.WriteValue(s)); - - writer.WriteEndObject(); } /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 2e94f6e8a..bddede097 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -11,6 +11,7 @@ using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -29,6 +30,11 @@ public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible /// public OpenApiInfo Info { get; set; } + /// + /// The default value for the $schema keyword within Schema Objects contained within this OAS document. This MUST be in the form of a URI. + /// + public string JsonSchemaDialect { get; set; } + /// /// An array of Server Objects, which provide connectivity information to a target server. /// @@ -89,6 +95,7 @@ public OpenApiDocument(OpenApiDocument document) { Workspace = document?.Workspace != null ? new(document?.Workspace) : null; Info = document?.Info != null ? new(document?.Info) : null; + JsonSchemaDialect = document?.JsonSchemaDialect ?? JsonSchemaDialect; Servers = document?.Servers != null ? new List(document.Servers) : null; Paths = document?.Paths != null ? new(document?.Paths) : null; Webhooks = document?.Webhooks != null ? new Dictionary(document.Webhooks) : null; @@ -99,67 +106,100 @@ public OpenApiDocument(OpenApiDocument document) Extensions = document?.Extensions != null ? new Dictionary(document.Extensions) : null; } + /// + /// Serialize to Open API v3.1 document. + /// + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); + + writer.WriteStartObject(); + + // openApi; + writer.WriteProperty(OpenApiConstants.OpenApi, "3.1.0"); + + // jsonSchemaDialect + writer.WriteProperty(OpenApiConstants.JsonSchemaDialect, JsonSchemaDialect); + + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (w, element) => element.SerializeAsV31(w), + (w, element) => element.SerializeAsV31WithoutReference(w)); + + // webhooks + writer.WriteOptionalMap( + OpenApiConstants.Webhooks, + Webhooks, + (w, key, component) => + { + if (component.Reference != null && + component.Reference.Type == ReferenceType.PathItem && + component.Reference.Id == key) + { + component.SerializeAsV31WithoutReference(w); + } + else + { + component.SerializeAsV31(w); + } + }); + + writer.WriteEndObject(); + } + /// /// Serialize to the latest patch of OpenAPI object V3.0. /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - writer.WriteStartObject(); + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); + writer.WriteStartObject(); + // openapi writer.WriteProperty(OpenApiConstants.OpenApi, "3.0.1"); + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (w, element) => element.SerializeAsV3(w), + (w, element) => element.SerializeAsV3WithoutReference(w)); + writer.WriteEndObject(); + } + /// + /// Serialize + /// + /// + /// + /// + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback, + Action action) + { // info - writer.WriteRequiredObject(OpenApiConstants.Info, Info, (w, i) => i.SerializeAsV3(w)); + writer.WriteRequiredObject(OpenApiConstants.Info, Info, callback); // servers - writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, callback); // paths - writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, (w, p) => p.SerializeAsV3(w)); - - // webhooks - writer.WriteOptionalMap( - OpenApiConstants.Webhooks, - Webhooks, - (w, key, component) => - { - if (component.Reference != null && - component.Reference.Type == ReferenceType.PathItem && - component.Reference.Id == key) - { - component.SerializeAsV3WithoutReference(w); - } - else - { - component.SerializeAsV3(w); - } - }); + writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, callback); // components - writer.WriteOptionalObject(OpenApiConstants.Components, Components, (w, c) => c.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Components, Components, callback); // security writer.WriteOptionalCollection( OpenApiConstants.Security, SecurityRequirements, - (w, s) => s.SerializeAsV3(w)); + callback); // tags - writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => t.SerializeAsV3WithoutReference(w)); + writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => action(w, t)); // external docs - writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, callback); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); - - writer.WriteEndObject(); + writer.WriteExtensions(Extensions, version); } /// @@ -167,10 +207,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs index ddb4162bc..3753b187c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs @@ -1,11 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -70,16 +72,32 @@ public OpenApiEncoding(OpenApiEncoding encoding) AllowReserved = encoding?.AllowReserved ?? AllowReserved; Extensions = encoding?.Extensions != null ? new Dictionary(encoding.Extensions) : null; } - + /// - /// Serialize to Open Api v3.0. + /// Serialize to Open Api v3.1 + /// + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + } + + /// + /// Serialize to Open Api v3.0 /// + /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull("writer"); - } + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + } + + /// + /// Serialize to Open Api v3.0. + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); @@ -87,7 +105,7 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.ContentType, ContentType); // headers - writer.WriteOptionalMap(OpenApiConstants.Headers, Headers, (w, h) => h.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Headers, Headers, callback); // style writer.WriteProperty(OpenApiConstants.Style, Style?.GetDisplayName()); @@ -99,7 +117,7 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiExample.cs b/src/Microsoft.OpenApi/Models/OpenApiExample.cs index 4d091a361..15e04fe5b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExample.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -73,15 +75,30 @@ public OpenApiExample(OpenApiExample example) UnresolvedReference = example?.UnresolvedReference ?? UnresolvedReference; } + /// + /// Serialize to Open Api v3.1 + /// + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// + /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -89,7 +106,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -97,7 +114,7 @@ public void SerializeAsV3(IOpenApiWriter writer) target = GetEffective(Reference.HostDocument); } } - target.SerializeAsV3WithoutReference(writer); + action(writer, target); } /// @@ -118,9 +135,22 @@ public OpenApiExample GetEffective(OpenApiDocument doc) } /// - /// Serialize to OpenAPI V3 document without using reference. + /// Serialize to OpenAPI V31 example without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1); + } + + /// + /// Serialize to OpenAPI V3 example without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version) { writer.WriteStartObject(); @@ -137,7 +167,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.ExternalValue, ExternalValue); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs index 40c26d429..aaeeee49c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -38,24 +40,41 @@ protected OpenApiExtensibleDictionary( /// public IDictionary Extensions { get; set; } = new Dictionary(); + + /// + /// Serialize to Open Api v3.1 + /// + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to Open Api v3.0 /// + /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); foreach (var item in this) { - writer.WriteRequiredObject(item.Key, item.Value, (w, p) => p.SerializeAsV3(w)); + writer.WriteRequiredObject(item.Key, item.Value, callback); } - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } @@ -65,10 +84,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs b/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs index 9ad3b9e55..0fb04914c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs @@ -43,7 +43,15 @@ public OpenApiExternalDocs(OpenApiExternalDocs externalDocs) Url = externalDocs?.Url != null ? new Uri(externalDocs.Url.OriginalString) : null; Extensions = externalDocs?.Extensions != null ? new Dictionary(externalDocs.Extensions) : null; } - + + /// + /// Serialize to Open Api v3.1. + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + WriteInternal(writer, OpenApiSpecVersion.OpenApi3_1); + } + /// /// Serialize to Open Api v3.0. /// @@ -51,7 +59,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { WriteInternal(writer, OpenApiSpecVersion.OpenApi3_0); } - + /// /// Serialize to Open Api v2.0. /// @@ -62,10 +70,7 @@ public void SerializeAsV2(IOpenApiWriter writer) private void WriteInternal(IOpenApiWriter writer, OpenApiSpecVersion specVersion) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index fb4411478..7f289b1c2 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -1,11 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -111,16 +113,29 @@ public OpenApiHeader(OpenApiHeader header) Content = header?.Content != null ? new Dictionary(header.Content) : null; Extensions = header?.Extensions != null ? new Dictionary(header.Extensions) : null; } - + + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -128,7 +143,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -136,8 +151,8 @@ public void SerializeAsV3(IOpenApiWriter writer) target = GetEffective(Reference.HostDocument); } } - target.SerializeAsV3WithoutReference(writer); - + + action(writer, target); } /// @@ -157,11 +172,26 @@ public OpenApiHeader GetEffective(OpenApiDocument doc) } } + /// + /// Serialize to OpenAPI V31 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + (writer, element) => element.SerializeAsV31(writer)); + } /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -187,19 +217,19 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - writer.WriteOptionalObject(OpenApiConstants.Schema, Schema, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Schema, Schema, callback); // example writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, s) => w.WriteAny(s)); // examples - writer.WriteOptionalMap(OpenApiConstants.Examples, Examples, (w, e) => e.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Examples, Examples, callback); // content - writer.WriteOptionalMap(OpenApiConstants.Content, Content, (w, c) => c.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Content, Content, callback); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } @@ -209,10 +239,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; diff --git a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs index 910d097e3..fa6c7690a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -72,25 +73,40 @@ public OpenApiInfo(OpenApiInfo info) License = info?.License != null ? new(info?.License) : null; Extensions = info?.Extensions != null ? new Dictionary(info.Extensions) : null; } - + + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + + // summary - present in 3.1 + writer.WriteProperty(OpenApiConstants.Summary, Summary); + writer.WriteEndObject(); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); // title writer.WriteProperty(OpenApiConstants.Title, Title); - - // summary - writer.WriteProperty(OpenApiConstants.Summary, Summary); - + // description writer.WriteProperty(OpenApiConstants.Description, Description); @@ -98,18 +114,16 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.TermsOfService, TermsOfService?.OriginalString); // contact object - writer.WriteOptionalObject(OpenApiConstants.Contact, Contact, (w, c) => c.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Contact, Contact, callback); // license object - writer.WriteOptionalObject(OpenApiConstants.License, License, (w, l) => l.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.License, License, callback); // version writer.WriteProperty(OpenApiConstants.Version, Version); // specification extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); - - writer.WriteEndObject(); + writer.WriteExtensions(Extensions, version); } /// @@ -117,10 +131,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs index f812b5b65..b78a92e07 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs @@ -49,13 +49,24 @@ public OpenApiLicense(OpenApiLicense license) Url = license?.Url != null ? new Uri(license.Url.OriginalString) : null; Extensions = license?.Extensions != null ? new Dictionary(license.Extensions) : null; } + + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + WriteInternal(writer, OpenApiSpecVersion.OpenApi3_1); + writer.WriteProperty(OpenApiConstants.Identifier, Identifier); + writer.WriteEndObject(); + } /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) - { - WriteInternal(writer, OpenApiSpecVersion.OpenApi3_0); + { + WriteInternal(writer, OpenApiSpecVersion.OpenApi3_0); + writer.WriteEndObject(); } /// @@ -64,30 +75,22 @@ public void SerializeAsV3(IOpenApiWriter writer) public void SerializeAsV2(IOpenApiWriter writer) { WriteInternal(writer, OpenApiSpecVersion.OpenApi2_0); + writer.WriteEndObject(); } private void WriteInternal(IOpenApiWriter writer, OpenApiSpecVersion specVersion) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); - + // name writer.WriteProperty(OpenApiConstants.Name, Name); - // identifier - writer.WriteProperty(OpenApiConstants.Identifier, Identifier); - // url writer.WriteProperty(OpenApiConstants.Url, Url?.OriginalString); // specification extensions writer.WriteExtensions(Extensions, specVersion); - - writer.WriteEndObject(); } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiLink.cs b/src/Microsoft.OpenApi/Models/OpenApiLink.cs index b682744e9..2e714c8fe 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLink.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLink.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -82,15 +84,28 @@ public OpenApiLink(OpenApiLink link) Reference = link?.Reference != null ? new(link?.Reference) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -98,7 +113,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -106,8 +121,7 @@ public void SerializeAsV3(IOpenApiWriter writer) target = GetEffective(Reference.HostDocument); } } - target.SerializeAsV3WithoutReference(writer); - + action(writer, target); } /// @@ -127,11 +141,23 @@ public OpenApiLink GetEffective(OpenApiDocument doc) } } + /// + /// Serialize to OpenAPI V31 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, (writer, element) => element.SerializeAsV31(writer)); + } /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, Action callback) { writer.WriteStartObject(); @@ -151,7 +177,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Description, Description); // server - writer.WriteOptionalObject(OpenApiConstants.Server, Server, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Server, Server, callback); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 63a58cd02..86de2d554 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -46,7 +48,7 @@ public class OpenApiMediaType : IOpenApiSerializable, IOpenApiExtensible /// /// Parameterless constructor /// - public OpenApiMediaType() {} + public OpenApiMediaType() { } /// /// Initializes a copy of an object @@ -60,33 +62,47 @@ public OpenApiMediaType(OpenApiMediaType mediaType) Extensions = mediaType?.Extensions != null ? new Dictionary(mediaType.Extensions) : null; } + /// + /// Serialize to Open Api v3.1. + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (w, element) => element.SerializeAsV31(w)); + } + /// /// Serialize to Open Api v3.0. /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (w, element) => element.SerializeAsV3(w)); + } + + /// + /// Serialize to Open Api v3.0. + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); + writer.WriteStartObject(); - + // schema - writer.WriteOptionalObject(OpenApiConstants.Schema, Schema, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Schema, Schema, callback); // example writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, e) => w.WriteAny(e)); // examples - writer.WriteOptionalMap(OpenApiConstants.Examples, Examples, (w, e) => e.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Examples, Examples, callback); // encoding - writer.WriteOptionalMap(OpenApiConstants.Encoding, Encoding, (w, e) => e.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Encoding, Encoding, callback); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); - + writer.WriteExtensions(Extensions, version); + writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs index c6f91fbd8..67ff239b2 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs @@ -58,15 +58,28 @@ public OpenApiOAuthFlow(OpenApiOAuthFlow oAuthFlow) Extensions = oAuthFlow?.Extensions != null ? new Dictionary(oAuthFlow.Extensions) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); @@ -83,7 +96,7 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteRequiredMap(OpenApiConstants.Scopes, Scopes, (w, s) => w.WriteValue(s)); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs index 8443e6730..d37088248 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -56,38 +58,52 @@ public OpenApiOAuthFlows(OpenApiOAuthFlows oAuthFlows) Extensions = oAuthFlows?.Extensions != null ? new Dictionary(oAuthFlows.Extensions) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + } + + /// + /// Serialize + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); // implicit - writer.WriteOptionalObject(OpenApiConstants.Implicit, Implicit, (w, o) => o.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Implicit, Implicit, callback); // password - writer.WriteOptionalObject(OpenApiConstants.Password, Password, (w, o) => o.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Password, Password, callback); // clientCredentials writer.WriteOptionalObject( OpenApiConstants.ClientCredentials, ClientCredentials, - (w, o) => o.SerializeAsV3(w)); + callback); // authorizationCode writer.WriteOptionalObject( OpenApiConstants.AuthorizationCode, AuthorizationCode, - (w, o) => o.SerializeAsV3(w)); + callback); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index d047b9cb6..f9209f7fa 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -131,15 +132,28 @@ public OpenApiOperation(OpenApiOperation operation) Extensions = operation?.Extensions != null ? new Dictionary(operation.Extensions) : null; } + /// + /// Serialize to Open Api v3.1. + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to Open Api v3.0. /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + } + + /// + /// Serialize to Open Api v3.0. + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); @@ -147,10 +161,7 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteOptionalCollection( OpenApiConstants.Tags, Tags, - (w, t) => - { - t.SerializeAsV3(w); - }); + callback); // summary writer.WriteProperty(OpenApiConstants.Summary, Summary); @@ -159,35 +170,35 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Description, Description); // externalDocs - writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, callback); // operationId writer.WriteProperty(OpenApiConstants.OperationId, OperationId); // parameters - writer.WriteOptionalCollection(OpenApiConstants.Parameters, Parameters, (w, p) => p.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.Parameters, Parameters, callback); // requestBody - writer.WriteOptionalObject(OpenApiConstants.RequestBody, RequestBody, (w, r) => r.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.RequestBody, RequestBody, callback); // responses - writer.WriteRequiredObject(OpenApiConstants.Responses, Responses, (w, r) => r.SerializeAsV3(w)); + writer.WriteRequiredObject(OpenApiConstants.Responses, Responses, callback); // callbacks - writer.WriteOptionalMap(OpenApiConstants.Callbacks, Callbacks, (w, c) => c.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Callbacks, Callbacks, callback); // deprecated writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false); // security - writer.WriteOptionalCollection(OpenApiConstants.Security, Security, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.Security, Security, callback); // servers - writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, callback); // specification extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); - + writer.WriteExtensions(Extensions,version); + writer.WriteEndObject(); } @@ -196,10 +207,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index e0e472721..9fad92698 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -1,12 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Runtime; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -168,16 +170,29 @@ public OpenApiParameter(OpenApiParameter parameter) AllowEmptyValue = parameter?.AllowEmptyValue ?? AllowEmptyValue; Deprecated = parameter?.Deprecated ?? Deprecated; } - + + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -185,16 +200,15 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else { - target = this.GetEffective(Reference.HostDocument); + target = GetEffective(Reference.HostDocument); } } - - target.SerializeAsV3WithoutReference(writer); + action(writer, target); } /// @@ -213,11 +227,27 @@ public OpenApiParameter GetEffective(OpenApiDocument doc) return this; } } - + + /// + /// Serialize to OpenAPI V3 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -249,19 +279,19 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - writer.WriteOptionalObject(OpenApiConstants.Schema, Schema, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Schema, Schema, callback); // example writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, s) => w.WriteAny(s)); // examples - writer.WriteOptionalMap(OpenApiConstants.Examples, Examples, (w, e) => e.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Examples, Examples, callback); // content - writer.WriteOptionalMap(OpenApiConstants.Content, Content, (w, c) => c.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Content, Content, callback); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } @@ -271,10 +301,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; if (Reference != null) diff --git a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs index ddd358dc2..02e9c2d50 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -85,22 +87,38 @@ public OpenApiPathItem(OpenApiPathItem pathItem) Reference = pathItem?.Reference != null ? new(pathItem?.Reference) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; if (Reference != null) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -108,7 +126,7 @@ public void SerializeAsV3(IOpenApiWriter writer) target = GetEffective(Reference.HostDocument); } } - target.SerializeAsV3WithoutReference(writer); + action(writer, target); } /// @@ -133,10 +151,7 @@ public OpenApiPathItem GetEffective(OpenApiDocument doc) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -193,12 +208,28 @@ public void SerializeAsV2WithoutReference(IOpenApiWriter writer) writer.WriteEndObject(); } + + /// + /// Serialize inline PathItem in OpenAPI V31 + /// + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + } /// /// Serialize inline PathItem in OpenAPI V3 /// /// public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -215,17 +246,17 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteOptionalObject( operation.Key.GetDisplayName(), operation.Value, - (w, o) => o.SerializeAsV3(w)); + callback); } // servers - writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, callback); // parameters - writer.WriteOptionalCollection(OpenApiConstants.Parameters, Parameters, (w, p) => p.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.Parameters, Parameters, callback); // specification extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiReference.cs b/src/Microsoft.OpenApi/Models/OpenApiReference.cs index a558e4394..aee6d2ead 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiReference.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -143,15 +144,32 @@ public OpenApiReference(OpenApiReference reference) HostDocument = new(reference?.HostDocument); } + /// + /// Serialize to Open Api v3.1. + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + // summary and description are in 3.1 but not in 3.0 + writer.WriteProperty(OpenApiConstants.Summary, Summary); + writer.WriteProperty(OpenApiConstants.Description, Description); + + SerializeInternal(writer); + } + /// /// Serialize to Open Api v3.0. /// public void SerializeAsV3(IOpenApiWriter writer) + { + SerializeInternal(writer); + } + + /// + /// Serialize + /// + private void SerializeInternal(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); if (Type == ReferenceType.Tag) { @@ -168,16 +186,10 @@ public void SerializeAsV3(IOpenApiWriter writer) } writer.WriteStartObject(); - - // summary - writer.WriteProperty(OpenApiConstants.Summary, Summary); - - // description - writer.WriteProperty(OpenApiConstants.Description, Description); // $ref writer.WriteProperty(OpenApiConstants.DollarRef, ReferenceV3); - + writer.WriteEndObject(); } @@ -186,10 +198,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); if (Type == ReferenceType.Tag) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index 70f1f742a..3d5cfdfd5 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -65,15 +66,28 @@ public OpenApiRequestBody(OpenApiRequestBody requestBody) Extensions = requestBody?.Extensions != null ? new Dictionary(requestBody.Extensions) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -81,7 +95,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -89,7 +103,7 @@ public void SerializeAsV3(IOpenApiWriter writer) target = GetEffective(Reference.HostDocument); } } - target.SerializeAsV3WithoutReference(writer); + action(writer, target); } /// @@ -109,10 +123,26 @@ public OpenApiRequestBody GetEffective(OpenApiDocument doc) } } + /// + /// Serialize to OpenAPI V31 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -120,13 +150,13 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Description, Description); // content - writer.WriteRequiredMap(OpenApiConstants.Content, Content, (w, c) => c.SerializeAsV3(w)); + writer.WriteRequiredMap(OpenApiConstants.Content, Content, callback); // required writer.WriteProperty(OpenApiConstants.Required, Required, false); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index a173f6c1a..10ac3de85 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -70,15 +72,28 @@ public OpenApiResponse(OpenApiResponse response) Reference = response?.Reference != null ? new(response?.Reference) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0. /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; @@ -86,7 +101,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -94,7 +109,7 @@ public void SerializeAsV3(IOpenApiWriter writer) target = GetEffective(Reference.HostDocument); } } - target.SerializeAsV3WithoutReference(writer); + action(writer, target); } /// @@ -113,11 +128,27 @@ public OpenApiResponse GetEffective(OpenApiDocument doc) return this; } } + + /// + /// Serialize to OpenAPI V3 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + (writer, element) => element.SerializeAsV31(writer)); + } /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -125,16 +156,16 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteRequiredProperty(OpenApiConstants.Description, Description); // headers - writer.WriteOptionalMap(OpenApiConstants.Headers, Headers, (w, h) => h.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Headers, Headers, callback); // content - writer.WriteOptionalMap(OpenApiConstants.Content, Content, (w, c) => c.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Content, Content, callback); // links - writer.WriteOptionalMap(OpenApiConstants.Links, Links, (w, l) => l.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Links, Links, callback); // extension - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } @@ -144,10 +175,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var target = this; diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 6019d7362..bc3a7e86a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -1,11 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -292,15 +294,31 @@ public OpenApiSchema(OpenApiSchema schema) Reference = schema?.Reference != null ? new(schema?.Reference) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), + (writer, element) => element.SerializeAsV31WithoutReference(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), + (writer, element) => element.SerializeAsV3WithoutReference(writer)); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var settings = writer.GetSettings(); var target = this; @@ -309,7 +327,7 @@ public void SerializeAsV3(IOpenApiWriter writer) { if (!settings.ShouldInlineReference(Reference)) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } else @@ -324,12 +342,11 @@ public void SerializeAsV3(IOpenApiWriter writer) if (!settings.LoopDetector.PushLoop(this)) { settings.LoopDetector.SaveLoop(this); - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } } - - target.SerializeAsV3WithoutReference(writer); + action(writer, target); if (Reference != null) { @@ -337,10 +354,24 @@ public void SerializeAsV3(IOpenApiWriter writer) } } + /// + /// Serialize to OpenAPI V31 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -397,22 +428,22 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Type, Type); // allOf - writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, callback); // anyOf - writer.WriteOptionalCollection(OpenApiConstants.AnyOf, AnyOf, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.AnyOf, AnyOf, callback); // oneOf - writer.WriteOptionalCollection(OpenApiConstants.OneOf, OneOf, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalCollection(OpenApiConstants.OneOf, OneOf, callback); // not - writer.WriteOptionalObject(OpenApiConstants.Not, Not, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Not, Not, callback); // items - writer.WriteOptionalObject(OpenApiConstants.Items, Items, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Items, Items, callback); // properties - writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, callback); // additionalProperties if (AdditionalPropertiesAllowed) @@ -420,7 +451,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteOptionalObject( OpenApiConstants.AdditionalProperties, AdditionalProperties, - (w, s) => s.SerializeAsV3(w)); + callback); } else { @@ -440,7 +471,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Nullable, Nullable, false); // discriminator - writer.WriteOptionalObject(OpenApiConstants.Discriminator, Discriminator, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Discriminator, Discriminator, callback); // readOnly writer.WriteProperty(OpenApiConstants.ReadOnly, ReadOnly, false); @@ -452,7 +483,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteOptionalObject(OpenApiConstants.Xml, Xml, (w, s) => s.SerializeAsV2(w)); // externalDocs - writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, s) => s.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, callback); // example writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, e) => w.WriteAny(e)); @@ -461,7 +492,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false); // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } @@ -497,10 +528,7 @@ internal void SerializeAsV2( ISet parentRequiredProperties, string propertyName) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); var settings = writer.GetSettings(); var target = this; diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs index d2564daf2..3ccf9b468 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -28,15 +30,28 @@ public OpenApiSecurityRequirement() { } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); + } + + /// + /// Serialize + /// + private void SerializeInternal(IOpenApiWriter writer, Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); @@ -53,7 +68,7 @@ public void SerializeAsV3(IOpenApiWriter writer) continue; } - securityScheme.SerializeAsV3(writer); + callback(writer, securityScheme); writer.WriteStartArray(); @@ -73,10 +88,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index 913e70441..06fecca13 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -77,7 +78,7 @@ public class OpenApiSecurityScheme : IOpenApiSerializable, IOpenApiReferenceable /// /// Parameterless constructor /// - public OpenApiSecurityScheme() {} + public OpenApiSecurityScheme() { } /// /// Initializes a copy of object @@ -97,30 +98,59 @@ public OpenApiSecurityScheme(OpenApiSecurityScheme securityScheme) Reference = securityScheme?.Reference != null ? new(securityScheme?.Reference) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer), SerializeAsV31WithoutReference); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer), SerializeAsV3WithoutReference); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, Action callback, + Action action) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); if (Reference != null) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } + + action(writer); + } - SerializeAsV3WithoutReference(writer); + /// + /// Serialize to OpenAPI V31 document without using reference. + /// + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + (writer, element) => element.SerializeAsV31(writer)); } /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -149,7 +179,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) case SecuritySchemeType.OAuth2: // This property apply to oauth2 type only. // flows - writer.WriteOptionalObject(OpenApiConstants.Flows, Flows, (w, o) => o.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.Flows, Flows, callback); break; case SecuritySchemeType.OpenIdConnect: // This property apply to openIdConnect only. @@ -159,7 +189,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) } // extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } @@ -169,10 +199,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); if (Reference != null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiServer.cs b/src/Microsoft.OpenApi/Models/OpenApiServer.cs index b3b1d1287..90252bd3f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiServer.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiServer.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -39,7 +41,7 @@ public class OpenApiServer : IOpenApiSerializable, IOpenApiExtensible /// /// Parameterless constructor /// - public OpenApiServer() {} + public OpenApiServer() { } /// /// Initializes a copy of an object @@ -52,15 +54,29 @@ public OpenApiServer(OpenApiServer server) Extensions = server?.Extensions != null ? new Dictionary(server.Extensions) : null; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); @@ -71,10 +87,10 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Description, Description); // variables - writer.WriteOptionalMap(OpenApiConstants.Variables, Variables, (w, v) => v.SerializeAsV3(w)); + writer.WriteOptionalMap(OpenApiConstants.Variables, Variables, callback); // specification extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs b/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs index 70164bc59..9bd923214 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs @@ -50,15 +50,28 @@ public OpenApiServerVariable(OpenApiServerVariable serverVariable) Extensions = serverVariable?.Extensions != null ? new Dictionary(serverVariable?.Extensions) : serverVariable?.Extensions; } + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); @@ -72,7 +85,7 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteOptionalCollection(OpenApiConstants.Enum, Enum, (w, s) => w.WriteValue(s)); // specification extensions - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiTag.cs b/src/Microsoft.OpenApi/Models/OpenApiTag.cs index ba4129142..64e62b062 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiTag.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiTag.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; +using static Microsoft.OpenApi.Extensions.OpenApiSerializableExtensions; namespace Microsoft.OpenApi.Models { @@ -46,7 +48,7 @@ public class OpenApiTag : IOpenApiSerializable, IOpenApiReferenceable, IOpenApiE /// /// Parameterless constructor /// - public OpenApiTag() {} + public OpenApiTag() { } /// /// Initializes a copy of an object @@ -60,20 +62,33 @@ public OpenApiTag(OpenApiTag tag) UnresolvedReference = tag?.UnresolvedReference ?? UnresolvedReference; Reference = tag?.Reference != null ? new(tag?.Reference) : null; } - + + /// + /// Serialize to Open Api v3.1 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); + } + /// /// Serialize to Open Api v3.0 /// public void SerializeAsV3(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); + } + + /// + /// Serialize to Open Api v3.0 + /// + private void SerializeInternal(IOpenApiWriter writer, Action callback) + { + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); if (Reference != null) { - Reference.SerializeAsV3(writer); + callback(writer, Reference); return; } @@ -83,7 +98,23 @@ public void SerializeAsV3(IOpenApiWriter writer) /// /// Serialize to OpenAPI V3 document without using reference. /// - public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public void SerializeAsV31WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + (writer, element) => element.SerializeAsV31(writer)); + } + + /// + /// Serialize to OpenAPI V3 document without using reference. + /// + public void SerializeAsV3WithoutReference(IOpenApiWriter writer) + { + SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + (writer, element) => element.SerializeAsV3(writer)); + } + + private void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + Action callback) { writer.WriteStartObject(); @@ -94,10 +125,10 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Description, Description); // external docs - writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV3(w)); + writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, callback); // extensions. - writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); + writer.WriteExtensions(Extensions, version); writer.WriteEndObject(); } @@ -107,10 +138,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer) /// public void SerializeAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); if (Reference != null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiXml.cs b/src/Microsoft.OpenApi/Models/OpenApiXml.cs index c6719d85e..358b42cb3 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiXml.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiXml.cs @@ -64,6 +64,14 @@ public OpenApiXml(OpenApiXml xml) Extensions = xml?.Extensions != null ? new Dictionary(xml.Extensions) : null; } + /// + /// Serialize to Open Api v3.0 + /// + public void SerializeAsV31(IOpenApiWriter writer) + { + Write(writer, OpenApiSpecVersion.OpenApi3_1); + } + /// /// Serialize to Open Api v3.0 /// @@ -82,10 +90,7 @@ public void SerializeAsV2(IOpenApiWriter writer) private void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } + writer = writer ?? throw Error.ArgumentNull(nameof(writer)); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/OpenApiSpecVersion.cs b/src/Microsoft.OpenApi/OpenApiSpecVersion.cs index 20e49af80..6c2a91716 100644 --- a/src/Microsoft.OpenApi/OpenApiSpecVersion.cs +++ b/src/Microsoft.OpenApi/OpenApiSpecVersion.cs @@ -16,6 +16,12 @@ public enum OpenApiSpecVersion /// /// Represents all patches of OpenAPI V3.0 spec (e.g. 3.0.0, 3.0.1) /// - OpenApi3_0 + OpenApi3_0, + + /// + /// Represents OpenAPI V3.1 spec + /// + OpenApi3_1 + } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 15b08166e..dd2235631 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -1559,7 +1559,7 @@ public void ParseDocumentWithWebhooksShouldSucceed() }; // Assert - diagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); + diagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_1 }); actual.Should().BeEquivalentTo(expected); } @@ -1769,6 +1769,7 @@ public void ParseDocumentsWithReusablePathItemInWebhooksSucceeds() Title = "Webhook Example", Version = "1.0.0" }, + JsonSchemaDialect = "http://json-schema.org/draft-07/schema#", Webhooks = components.PathItems, Components = components }; @@ -1776,7 +1777,7 @@ public void ParseDocumentsWithReusablePathItemInWebhooksSucceeds() // Assert actual.Should().BeEquivalentTo(expected); context.Should().BeEquivalentTo( - new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); + new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_1}); } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithReusablePaths.yaml b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithReusablePaths.yaml index ffb3aa252..de2f05420 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithReusablePaths.yaml +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithReusablePaths.yaml @@ -2,6 +2,7 @@ info: title: Webhook Example version: 1.0.0 +jsonSchemaDialect: "http://json-schema.org/draft-07/schema#" webhooks: /pets: "$ref": '#/components/pathItems/pets' diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs index d557f4c4c..7c6365ce4 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs @@ -669,25 +669,6 @@ public void SerializeComponentsWithPathItemsAsJsonWorks() { // Arrange var expected = @"{ - ""schemas"": { - ""schema1"": { - ""properties"": { - ""property2"": { - ""type"": ""integer"" - }, - ""property3"": { - ""$ref"": ""#/components/schemas/schema2"" - } - } - }, - ""schema2"": { - ""properties"": { - ""property2"": { - ""type"": ""integer"" - } - } - } - }, ""pathItems"": { ""/pets"": { ""post"": { @@ -708,10 +689,29 @@ public void SerializeComponentsWithPathItemsAsJsonWorks() } } } + }, + ""schemas"": { + ""schema1"": { + ""properties"": { + ""property2"": { + ""type"": ""integer"" + }, + ""property3"": { + ""$ref"": ""#/components/schemas/schema2"" + } + } + }, + ""schema2"": { + ""properties"": { + ""property2"": { + ""type"": ""integer"" + } + } + } } }"; // Act - var actual = ComponentsWithPathItem.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); + var actual = ComponentsWithPathItem.SerializeAsJson(OpenApiSpecVersion.OpenApi3_1); // Assert actual = actual.MakeLineBreaksEnvironmentNeutral(); @@ -723,18 +723,7 @@ public void SerializeComponentsWithPathItemsAsJsonWorks() public void SerializeComponentsWithPathItemsAsYamlWorks() { // Arrange - var expected = @"schemas: - schema1: - properties: - property2: - type: integer - property3: - $ref: '#/components/schemas/schema2' - schema2: - properties: - property2: - type: integer -pathItems: + var expected = @"pathItems: /pets: post: requestBody: @@ -745,10 +734,21 @@ public void SerializeComponentsWithPathItemsAsYamlWorks() $ref: '#/components/schemas/schema1' responses: '200': - description: Return a 200 status to indicate that the data was received successfully"; + description: Return a 200 status to indicate that the data was received successfully +schemas: + schema1: + properties: + property2: + type: integer + property3: + $ref: '#/components/schemas/schema2' + schema2: + properties: + property2: + type: integer"; // Act - var actual = ComponentsWithPathItem.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); + var actual = ComponentsWithPathItem.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); // Assert actual = actual.MakeLineBreaksEnvironmentNeutral(); diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=False.verified.txt index 73cc1b716..4eebd3082 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=False.verified.txt @@ -1,31 +1,10 @@ { - "openapi": "3.0.1", + "openapi": "3.1.0", "info": { "title": "Webhook Example", "version": "1.0.0" }, "paths": { }, - "webhooks": { - "newPet": { - "post": { - "requestBody": { - "description": "Information about a new pet in the system", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - } - }, "components": { "schemas": { "Pet": { @@ -47,5 +26,26 @@ } } } + }, + "webhooks": { + "newPet": { + "post": { + "requestBody": { + "description": "Information about a new pet in the system", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + } } } \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=True.verified.txt index a23dd5675..d105617d2 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeDocumentWithWebhooksAsV3JsonWorks_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"openapi":"3.0.1","info":{"title":"Webhook Example","version":"1.0.0"},"paths":{},"webhooks":{"newPet":{"post":{"requestBody":{"description":"Information about a new pet in the system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pet"}}}},"responses":{"200":{"description":"Return a 200 status to indicate that the data was received successfully"}}}}},"components":{"schemas":{"Pet":{"required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}} \ No newline at end of file +{"openapi":"3.1.0","info":{"title":"Webhook Example","version":"1.0.0"},"paths":{},"components":{"schemas":{"Pet":{"required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"webhooks":{"newPet":{"post":{"requestBody":{"description":"Information about a new pet in the system","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pet"}}}},"responses":{"200":{"description":"Return a 200 status to indicate that the data was received successfully"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 6a185b556..b33055936 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -12,9 +12,11 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Readers; using Microsoft.OpenApi.Writers; +using Microsoft.VisualBasic; using VerifyXunit; using Xunit; using Xunit.Abstractions; +using static System.Net.Mime.MediaTypeNames; namespace Microsoft.OpenApi.Tests.Models { @@ -1439,7 +1441,7 @@ public async void SerializeDocumentWithWebhooksAsV3JsonWorks(bool produceTerseOu var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput }); // Act - DocumentWithWebhooks.SerializeAsV3(writer); + DocumentWithWebhooks.SerializeAsV31(writer); writer.Flush(); var actual = outputStringWriter.GetStringBuilder().ToString(); @@ -1451,23 +1453,11 @@ public async void SerializeDocumentWithWebhooksAsV3JsonWorks(bool produceTerseOu public void SerializeDocumentWithWebhooksAsV3YamlWorks() { // Arrange - var expected = @"openapi: 3.0.1 + var expected = @"openapi: '3.1.0' info: title: Webhook Example version: 1.0.0 paths: { } -webhooks: - newPet: - post: - requestBody: - description: Information about a new pet in the system - content: - application/json: - schema: - $ref: '#/components/schemas/Pet' - responses: - '200': - description: Return a 200 status to indicate that the data was received successfully components: schemas: Pet: @@ -1481,15 +1471,55 @@ public void SerializeDocumentWithWebhooksAsV3YamlWorks() name: type: string tag: - type: string"; + type: string +webhooks: + newPet: + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + responses: + '200': + description: Return a 200 status to indicate that the data was received successfully"; // Act - var actual = DocumentWithWebhooks.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); + var actual = DocumentWithWebhooks.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); // Assert actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); Assert.Equal(expected, actual); } + + [Fact] + public void SerializeDocumentWithRootJsonSchemaDialectPropertyWorks() + { + // Arrange + var doc = new OpenApiDocument + { + Info = new OpenApiInfo + { + Title = "JsonSchemaDialectTest", + Version = "1.0.0" + }, + JsonSchemaDialect = "http://json-schema.org/draft-07/schema#" + }; + + var expected = @"openapi: '3.1.0' +jsonSchemaDialect: http://json-schema.org/draft-07/schema# +info: + title: JsonSchemaDialectTest + version: 1.0.0 +paths: { }"; + + // Act + var actual = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); + + // Assert + Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral()); + } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs index e9acbd486..74eb2d6e9 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs @@ -206,16 +206,16 @@ public void InfoVersionShouldAcceptDateStyledAsVersions() } [Fact] - public void SerializeInfoObjectWithSummaryAsV3YamlWorks() + public void SerializeInfoObjectWithSummaryAsV31YamlWorks() { // Arrange var expected = @"title: Sample Pet Store App -summary: This is a sample server for a pet store. description: This is a sample server for a pet store. -version: '1.1.1'"; +version: '1.1.1' +summary: This is a sample server for a pet store."; // Act - var actual = InfoWithSummary.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); + var actual = InfoWithSummary.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); // Assert actual = actual.MakeLineBreaksEnvironmentNeutral(); @@ -224,18 +224,18 @@ public void SerializeInfoObjectWithSummaryAsV3YamlWorks() } [Fact] - public void SerializeInfoObjectWithSummaryAsV3JsonWorks() + public void SerializeInfoObjectWithSummaryAsV31JsonWorks() { // Arrange var expected = @"{ ""title"": ""Sample Pet Store App"", - ""summary"": ""This is a sample server for a pet store."", ""description"": ""This is a sample server for a pet store."", - ""version"": ""1.1.1"" + ""version"": ""1.1.1"", + ""summary"": ""This is a sample server for a pet store."" }"; // Act - var actual = InfoWithSummary.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); + var actual = InfoWithSummary.SerializeAsJson(OpenApiSpecVersion.OpenApi3_1); // Assert actual = actual.MakeLineBreaksEnvironmentNeutral(); diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs index 3f5ef03b6..2d81ac3c5 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs @@ -141,7 +141,7 @@ public void SerializeLicenseWithIdentifierAsJsonWorks() }"; // Act - var actual = LicenseWithIdentifier.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); + var actual = LicenseWithIdentifier.SerializeAsJson(OpenApiSpecVersion.OpenApi3_1); // Assert Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral()); @@ -155,7 +155,7 @@ public void SerializeLicenseWithIdentifierAsYamlWorks() identifier: Apache-2.0"; // Act - var actual = LicenseWithIdentifier.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); + var actual = LicenseWithIdentifier.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); // Assert Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral()); diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs index 7d630c5f6..47c083a0f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs @@ -114,8 +114,7 @@ public void SerializeSecurityRequirementWithReferencedSecuritySchemeAsV3JsonWork }"; // Act - var actual = - SecurityRequirementWithReferencedSecurityScheme.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); + var actual = SecurityRequirementWithReferencedSecurityScheme.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // Assert actual = actual.MakeLineBreaksEnvironmentNeutral(); @@ -151,8 +150,7 @@ public void SerializeSecurityRequirementWithReferencedSecuritySchemeAsV2JsonWork } [Fact] - public void - SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV3JsonShouldSkipUnserializableKeyValuePair() + public void SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV3JsonShouldSkipUnserializableKeyValuePair() { // Arrange var expected = @@ -166,8 +164,7 @@ public void }"; // Act - var actual = - SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); + var actual = SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // Assert actual = actual.MakeLineBreaksEnvironmentNeutral(); @@ -176,8 +173,7 @@ public void } [Fact] - public void - SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2JsonShouldSkipUnserializableKeyValuePair() + public void SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2JsonShouldSkipUnserializableKeyValuePair() { // Arrange var expected = diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index b42325207..5c14ab394 100755 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -308,12 +308,14 @@ namespace Microsoft.OpenApi.Interfaces Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } bool UnresolvedReference { get; set; } void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer); + void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer); void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer); } public interface IOpenApiSerializable : Microsoft.OpenApi.Interfaces.IOpenApiElement { void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer); void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer); + void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer); } } namespace Microsoft.OpenApi @@ -334,6 +336,7 @@ namespace Microsoft.OpenApi { OpenApi2_0 = 0, OpenApi3_0 = 1, + OpenApi3_1 = 2, } } namespace Microsoft.OpenApi.Models @@ -351,6 +354,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiComponents : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -370,6 +375,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary SecuritySchemes { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public static class OpenApiConstants { @@ -429,6 +435,7 @@ namespace Microsoft.OpenApi.Models public const string In = "in"; public const string Info = "info"; public const string Items = "items"; + public const string JsonSchemaDialect = "jsonSchemaDialect"; public const string Jwt = "JWT"; public const string License = "license"; public const string Links = "links"; @@ -512,6 +519,7 @@ namespace Microsoft.OpenApi.Models public System.Uri Url { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiDiscriminator : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -521,6 +529,7 @@ namespace Microsoft.OpenApi.Models public string PropertyName { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiDocument : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -531,6 +540,7 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } public string HashCode { get; } public Microsoft.OpenApi.Models.OpenApiInfo Info { get; set; } + public string JsonSchemaDialect { get; set; } public Microsoft.OpenApi.Models.OpenApiPaths Paths { get; set; } public System.Collections.Generic.IList SecurityRequirements { get; set; } public System.Collections.Generic.IList Servers { get; set; } @@ -541,6 +551,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IEnumerable ResolveReferences() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public static string GenerateHashValue(Microsoft.OpenApi.Models.OpenApiDocument doc) { } } public class OpenApiEncoding : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -555,6 +566,7 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiError { @@ -580,6 +592,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public abstract class OpenApiExtensibleDictionary : System.Collections.Generic.Dictionary, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -590,6 +604,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary Extensions { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiExternalDocs : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -600,6 +615,7 @@ namespace Microsoft.OpenApi.Models public System.Uri Url { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiHeader : Microsoft.OpenApi.Interfaces.IEffective, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -623,6 +639,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiInfo : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -639,6 +657,7 @@ namespace Microsoft.OpenApi.Models public string Version { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiLicense : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -650,6 +669,7 @@ namespace Microsoft.OpenApi.Models public System.Uri Url { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiLink : Microsoft.OpenApi.Interfaces.IEffective, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -668,6 +688,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiMediaType : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -681,6 +703,7 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiOAuthFlow : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -693,6 +716,7 @@ namespace Microsoft.OpenApi.Models public System.Uri TokenUrl { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiOAuthFlows : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -705,6 +729,7 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Models.OpenApiOAuthFlow Password { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiOperation : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -726,6 +751,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IList Tags { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiParameter : Microsoft.OpenApi.Interfaces.IEffective, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -752,6 +778,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiPathItem : Microsoft.OpenApi.Interfaces.IEffective, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -771,6 +799,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiPaths : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary @@ -794,6 +824,7 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Models.ReferenceType? Type { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiRequestBody : Microsoft.OpenApi.Interfaces.IEffective, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -809,6 +840,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiResponse : Microsoft.OpenApi.Interfaces.IEffective, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -826,6 +859,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiResponses : Microsoft.OpenApi.Models.OpenApiExtensibleDictionary @@ -880,6 +915,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -887,6 +924,7 @@ namespace Microsoft.OpenApi.Models public OpenApiSecurityRequirement() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiSecurityScheme : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -906,6 +944,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiServer : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -918,6 +958,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary Variables { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiServerVariable : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -929,6 +970,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary Extensions { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiTag : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -943,6 +985,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiXml : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -957,6 +1001,7 @@ namespace Microsoft.OpenApi.Models public bool Wrapped { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public enum OperationType {