From a1b5328c2651b4403a502a7a7e73bde02bebe34e Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Fri, 27 Oct 2017 13:10:30 -0700 Subject: [PATCH 01/13] add the write functionality for each open api element --- src/Microsoft.OpenApi.Workbench/MainModel.cs | 15 +- .../Interfaces/IOpenApiElement.cs | 2 +- .../Interfaces/IOpenApiWritable.cs | 27 +++ .../Models/OpenApiCallback.cs | 34 ++++ .../Models/OpenApiComponents.cs | 42 +++++ .../Models/OpenApiContact.cs | 31 ++++ .../Models/OpenApiDiscriminator.cs | 20 ++- .../Models/OpenApiDocument.cs | 102 +++++++++++ .../Models/OpenApiExample.cs | 39 ++++- .../Models/OpenApiExternalDocs.cs | 30 ++++ src/Microsoft.OpenApi/Models/OpenApiHeader.cs | 67 ++++++++ src/Microsoft.OpenApi/Models/OpenApiInfo.cs | 47 +++++ .../Models/OpenApiLicense.cs | 30 ++++ src/Microsoft.OpenApi/Models/OpenApiLink.cs | 33 ++++ .../Models/OpenApiMediaType.cs | 26 +++ .../Models/OpenApiOAuthFlow.cs | 36 ++++ .../Models/OpenApiOAuthFlows.cs | 27 +++ .../Models/OpenApiOperation.cs | 91 ++++++++++ .../Models/OpenApiParameter.cs | 86 ++++++++++ .../Models/OpenApiPathItem.cs | 69 ++++++++ src/Microsoft.OpenApi/Models/OpenApiPaths.cs | 39 +++++ .../Models/OpenApiReference.cs | 19 ++- .../Models/OpenApiRequestBody.cs | 35 ++++ .../Models/OpenApiResponse.cs | 74 ++++++++ src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 161 ++++++++++++++++++ .../Models/OpenApiSecurityRequirement.cs | 60 +++++++ .../Models/OpenApiSecurityScheme.cs | 96 +++++++++++ src/Microsoft.OpenApi/Models/OpenApiServer.cs | 26 +++ .../Models/OpenApiServerVariable.cs | 26 +++ src/Microsoft.OpenApi/Models/OpenApiTag.cs | 33 ++++ src/Microsoft.OpenApi/Models/OpenApiXml.cs | 17 ++ .../OpenApiElementSerializeExtensions.cs | 96 +++++++++++ .../DownGradeTests.cs | 4 +- test/Microsoft.OpenApi.Tests/ExampleTests.cs | 3 +- .../OpenApiExternalDocsExtensionsTests.cs | 74 ++++++++ .../OpenApiSerializerTestHelper.cs | 52 ++++++ 36 files changed, 1650 insertions(+), 19 deletions(-) create mode 100644 src/Microsoft.OpenApi/Interfaces/IOpenApiWritable.cs create mode 100644 src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs create mode 100644 test/Microsoft.OpenApi.Tests/Serialization/OpenApiExternalDocsExtensionsTests.cs create mode 100644 test/Microsoft.OpenApi.Tests/Serialization/OpenApiSerializerTestHelper.cs diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs index 16dc6fd59..3773892e2 100644 --- a/src/Microsoft.OpenApi.Workbench/MainModel.cs +++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs @@ -121,18 +121,11 @@ internal void Validate() private string WriteContents(OpenApiDocument doc) { - Func writerFactory = s => (this.format == "Yaml" ? new OpenApiYamlWriter(new StreamWriter(s)) : (IOpenApiWriter)new OpenApiJsonWriter(new StreamWriter(s))); - IOpenApiStructureWriter writer; - if (IsV3) - { - writer = new OpenApiV3Writer(writerFactory); - } else - { - writer = new OpenApiV2Writer(writerFactory); - } - var outputstream = new MemoryStream(); - writer.Write(outputstream, doc); + doc.Serialize(outputstream, + IsV3 ? OpenApiSpecVersion.OpenApi3_0 : OpenApiSpecVersion.OpenApi2_0, + this.format == "Yaml" ? OpenApiFormat.Yaml : OpenApiFormat.Json); + outputstream.Position = 0; return new StreamReader(outputstream).ReadToEnd(); diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs index 3a3a7d195..92b8bad3b 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi.Interfaces /// /// Represents an Open API element. /// - public interface IOpenApiElement + public interface IOpenApiElement : IOpenApiWritable { } } diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiWritable.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiWritable.cs new file mode 100644 index 000000000..a696d4fd4 --- /dev/null +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiWritable.cs @@ -0,0 +1,27 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OpenApi.Writers; + +namespace Microsoft.OpenApi.Interfaces +{ + /// + /// Represents an Open API element is writable. + /// + public interface IOpenApiWritable + { + /// + /// Write Open API element to v3.0. + /// + /// The writer. + void WriteAsV3(IOpenApiWriter writer); + + /// + /// Write Open API element to v2.0. + /// + /// The writer. + void WriteAsV2(IOpenApiWriter writer); + } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs index 1ff8362f7..c197b03fc 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -19,5 +20,38 @@ public class OpenApiCallback : IOpenApiReference, IOpenApiExtension public OpenApiReference Pointer { get; set; } public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + foreach (var item in PathItems) + { + writer.WriteObject(item.Key.Expression, item.Value, (w, p) => p.WriteAsV3(w)); + } + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index 6fa48ed9d..2437d6cab 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -37,5 +38,46 @@ public bool IsEmpty() || this.Links.Count > 0 || this.Callbacks.Count > 0); } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteMap("schemas", Schemas, (w, s) => s.WriteAsV3(w)); + writer.WriteMap("responses", Responses, (w, r) => r.WriteAsV3(w)); + writer.WriteMap("parameters", Parameters, (w, p) => p.WriteAsV3(w)); + writer.WriteMap("examples", Examples, (w, e) => e.WriteAsV3(w)); + writer.WriteMap("requestBodies", RequestBodies, (w, r) => r.WriteAsV3(w)); + writer.WriteMap("headers", Headers, (w, h) => h.WriteAsV3(w)); + writer.WriteMap("securitySchemes", SecuritySchemes, (w, s) => s.WriteAsV3(w)); + writer.WriteMap("links", Links, (w, link) => link.WriteAsV3(w)); + writer.WriteMap("callbacks", Callbacks, (w, c) => c.WriteAsV3(w)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteMap("definitions", Schemas, (w, s) => s.WriteAsV2(w)); + writer.WriteMap("responses", Responses, (w, r) => r.WriteAsV2(w)); + writer.WriteMap("parameters", Parameters, (w, p) => p.WriteAsV2(w)); + writer.WriteMap("securityDefinitions", SecuritySchemes, (w, s) => s.WriteAsV2(w)); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiContact.cs b/src/Microsoft.OpenApi/Models/OpenApiContact.cs index 76d40b954..ae96ed1e7 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiContact.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiContact.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -35,5 +36,35 @@ public class OpenApiContact : IOpenApiExtension /// This object MAY be extended with Specification Extensions. /// public IDictionary Extensions { get; set; } = new Dictionary(); + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + WriteInternal(writer); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + WriteInternal(writer); + } + + private void WriteInternal(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("name", Name); + writer.WriteStringProperty("url", Url?.OriginalString); + writer.WriteStringProperty("email", Email); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs index b9bbe7cc3..9ab8a739d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs @@ -3,12 +3,30 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; + namespace Microsoft.OpenApi.Models { /// /// Discriminator object. /// - internal class OpenApiDiscriminator + public class OpenApiDiscriminator : IOpenApiElement { + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + // nothing here + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index be71d9d2a..f03c2df9d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -4,10 +4,12 @@ // ------------------------------------------------------------ using System; +using System.Linq; using System.Collections.Generic; using System.Text.RegularExpressions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -46,5 +48,105 @@ public void CreatePath(string key, Action configure) configure(pathItem); Paths.Add(key, pathItem); } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WritePropertyName("openapi"); + writer.WriteValue("3.0.0"); + + writer.WriteObject("info", Info, (w, i) => i.WriteAsV3(w)); + writer.WriteList("servers", Servers, (w, s) => s.WriteAsV3(w)); + writer.WritePropertyName("paths"); + + writer.WriteStartObject(); + Paths.WriteAsV3(writer); + writer.WriteEndObject(); + + writer.WriteList("tags", Tags, (w, t) => t.WriteAsV3(w)); + if (!Components.IsEmpty()) + { + writer.WriteObject("components", Components, (w, c) => c.WriteAsV3(w)); + } + if (ExternalDocs.Url != null) + { + writer.WriteObject("externalDocs", ExternalDocs, (w, e) => e.WriteAsV3(w)); + } + writer.WriteList("security", SecurityRequirements, (w, s) => s.WriteAsV3(w)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WritePropertyName("swagger"); + writer.WriteValue("2.0"); + + writer.WriteObject("info", Info, (w, i) => i.WriteAsV2(w)); + SerializeHostInfo(writer, Servers); + + writer.WritePropertyName("paths"); + + writer.WriteStartObject(); + Paths.WriteAsV2(writer); + writer.WriteEndObject(); + + writer.WriteList("tags", Tags, (w, t) => t.WriteAsV2(w)); + if (!Components.IsEmpty()) + { + Components.WriteAsV2(writer); + } + if (ExternalDocs.Url != null) + { + writer.WriteObject("externalDocs", ExternalDocs, (w, e) => e.WriteAsV2(w)); + } + writer.WriteList("security", SecurityRequirements, (w, s) => s.WriteAsV2(w)); + writer.WriteEndObject(); + } + + private static void SerializeHostInfo(IOpenApiWriter writer, IList servers) + { + if (servers == null || servers.Count == 0) + { + return; + } + + var firstServer = servers.First(); + + var url = new Uri(firstServer.Url); + + writer.WriteStringProperty("host", url.GetComponents(UriComponents.Host | UriComponents.Port, UriFormat.SafeUnescaped)); + + writer.WriteStringProperty("basePath", url.AbsolutePath); + + var schemes = servers.Select(s => new Uri(s.Url).Scheme).Distinct(); + + writer.WritePropertyName("schemes"); + + writer.WriteStartArray(); + + foreach (var scheme in schemes) + { + writer.WriteValue(scheme); + } + + writer.WriteEndArray(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiExample.cs b/src/Microsoft.OpenApi/Models/OpenApiExample.cs index fd0d2c71c..c72cb4ff4 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExample.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -38,5 +39,41 @@ public OpenApiReference Pointer { get; set; } - } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + writer.WriteStringProperty("summary", Summary); + writer.WriteStringProperty("description", Description); + if (Value != null) + { + writer.WritePropertyName("value"); + writer.WriteRaw(Value); + } + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } + } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs b/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs index bd01776aa..cfa4a2236 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -29,5 +30,34 @@ public class OpenApiExternalDocs : IOpenApiExtension /// This object MAY be extended with Specification Extensions. /// public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + WriteInternal(writer); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + WriteInternal(writer); + } + + private void WriteInternal(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("description", Description); + writer.WriteStringProperty("url", Url?.OriginalString); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index 5361c5e14..f6d7d9ad5 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -29,5 +30,71 @@ public class OpenApiHeader : IOpenApiReference, IOpenApiExtension public IDictionary Content { get; set; } public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + + writer.WriteStringProperty("description", Description); + writer.WriteBoolProperty("required", Required, false); + writer.WriteBoolProperty("deprecated", Deprecated, false); + writer.WriteBoolProperty("allowEmptyValue", AllowEmptyValue, false); + writer.WriteStringProperty("style", Style); + writer.WriteBoolProperty("explode", Explode, false); + writer.WriteBoolProperty("allowReserved", AllowReserved, false); + writer.WriteObject("schema", Schema, (w, s) => s.WriteAsV3(w)); + writer.WriteList("examples", Examples, (w, e) => e.WriteAsV3(w)); + writer.WriteObject("example", Example, (w, s) => w.WriteRaw(s)); + writer.WriteMap("content", Content, (w, c) => c.WriteAsV3(w)); + + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + + writer.WriteStringProperty("description", Description); + writer.WriteBoolProperty("required", Required, false); + writer.WriteBoolProperty("deprecated", Deprecated, false); + writer.WriteBoolProperty("allowEmptyValue", AllowEmptyValue, false); + writer.WriteStringProperty("style", Style); + writer.WriteBoolProperty("explode", Explode, false); + writer.WriteBoolProperty("allowReserved", AllowReserved, false); + writer.WriteObject("schema", Schema, (w, s) => s.WriteAsV2(w)); + writer.WriteStringProperty("example", Example); + + writer.WriteEndObject(); + } + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs index c63538aac..1efaf72fc 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs @@ -8,6 +8,7 @@ using System.Text.RegularExpressions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -64,5 +65,51 @@ public string TermsOfService public IDictionary Extensions { get; set; } = new Dictionary(); private static Regex versionRegex = new Regex(@"\d+\.\d+\.\d+"); + + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("title", Title); + writer.WriteStringProperty("description", Description); + writer.WriteStringProperty("termsOfService", TermsOfService); + writer.WriteObject("contact", Contact, (w, c) => c.WriteAsV3(w)); + writer.WriteObject("license", License, (w, l) => l.WriteAsV3(w)); + writer.WriteStringProperty("version", Version.ToString()); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("title", Title); + + writer.WriteStringProperty("description", Description); + + writer.WriteStringProperty("termsOfService", TermsOfService); + + writer.WriteObject("contact", Contact, (w, c) => c.WriteAsV2(w)); + + writer.WriteObject("license", License, (w, l) => l.WriteAsV2(w)); + + writer.WriteStringProperty("version", Version.ToString()); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs index 20b5c8bce..9da656565 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -29,5 +30,34 @@ public class OpenApiLicense : IOpenApiExtension /// This object MAY be extended with Specification Extensions. /// public IDictionary Extensions { get; set; } = new Dictionary(); + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + WriteInternal(writer); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + WriteInternal(writer); + } + + private void WriteInternal(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("name", Name); + writer.WriteStringProperty("url", Url?.OriginalString); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiLink.cs b/src/Microsoft.OpenApi/Models/OpenApiLink.cs index f9e9e384b..64495eca7 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLink.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLink.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -24,5 +25,37 @@ public class OpenApiLink : IOpenApiReference, IOpenApiExtension public IDictionary Extensions { get; set; } public OpenApiReference Pointer { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + writer.WriteStringProperty("href", Href); + writer.WriteStringProperty("operationId", OperationId); + writer.WriteMap("parameters", Parameters, (w, x) => { w.WriteValue(x.ToString()); }); + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 2dd4ad4a8..b0bedd4e5 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -19,5 +20,30 @@ public class OpenApiMediaType : IOpenApiExtension public string Example { get; set; } public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteObject("schema", Schema, (w, s) => s.WriteAsV3(w)); + writer.WriteObject("example", Example, (w, e) => w.WriteRaw(e)); + writer.WriteMap("examples", Examples, (w, e) => e.WriteAsV3(w)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs index 17415b5fe..1cd6b4a14 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -39,5 +40,40 @@ public class OpenApiOAuthFlow : IOpenApiExtension /// Specification Extensions. /// public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("authorizationUrl", AuthorizationUrl?.ToString()); + writer.WriteStringProperty("tokenUrl", TokenUrl?.ToString()); + writer.WriteStringProperty("refreshUrl", RefreshUrl?.ToString()); + writer.WriteMap("scopes", Scopes, (w, s) => w.WriteValue(s)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("authorizationUrl", AuthorizationUrl?.ToString()); + writer.WriteStringProperty("tokenUrl", TokenUrl?.ToString()); + writer.WriteMap("scopes", Scopes, (w, s) => w.WriteValue(s)); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs index 6141bcb4c..a18cbaef5 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -38,5 +39,31 @@ public class OpenApiOAuthFlows : IOpenApiExtension /// Specification Extensions. /// public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteObject("implicit", Implicit, (w, o) => o.WriteAsV3(w)); + writer.WriteObject("password", Password, (w, o) => o.WriteAsV3(w)); + writer.WriteObject("clientCredentials", ClientCredentials, (w, o) => o.WriteAsV3(w)); + writer.WriteObject("authorizationCode", AuthorizationCode, (w, o) => o.WriteAsV3(w)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index cc2fb138f..24df75d63 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -4,9 +4,11 @@ // ------------------------------------------------------------ using System; +using System.Linq; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -37,5 +39,94 @@ public void CreateResponse(string key, Action configure) configure(response); Responses.Add(key, response); } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteList("tags", Tags, (w, t) => t.WriteAsV3(w)); + writer.WriteStringProperty("summary", Summary); + writer.WriteStringProperty("description", Description); + writer.WriteObject("externalDocs", ExternalDocs, (w, e) => e.WriteAsV3(w)); + + writer.WriteStringProperty("operationId", OperationId); + writer.WriteList("parameters", Parameters, (w, p) => p.WriteAsV3(w)); + writer.WriteObject("requestBody", RequestBody, (w, r) => r.WriteAsV3(w)); + writer.WriteMap("responses", Responses, (w, r) => r.WriteAsV3(w)); + writer.WriteMap("callbacks", Callbacks, (w, c) => c.WriteAsV3(w)); + writer.WriteBoolProperty("deprecated", Deprecated, OpenApiOperation.DeprecatedDefault); + writer.WriteList("security", Security, (w, s) => s.WriteAsV3(w)); + writer.WriteList("servers", Servers, (w, s) => s.WriteAsV3(w)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteList("tags", Tags, (w, t) => t.WriteAsV2(w)); + writer.WriteStringProperty("summary", Summary); + writer.WriteStringProperty("description", Description); + writer.WriteObject("externalDocs", ExternalDocs, (w, e) => e.WriteAsV2(w)); + + writer.WriteStringProperty("operationId", OperationId); + + var parameters = new List(Parameters); + + OpenApiParameter bodyParameter = null; + if (RequestBody != null) + { + writer.WritePropertyName("consumes"); + writer.WriteStartArray(); + var consumes = RequestBody.Content.Keys.Distinct(); + foreach (var mediaType in consumes) + { + writer.WriteValue(mediaType); + } + writer.WriteEndArray(); + + // Create bodyParameter + bodyParameter = new BodyParameter() + { + Name = "body", + Description = RequestBody.Description, + Schema = RequestBody.Content.First().Value.Schema + }; + // add to parameters + parameters.Add(bodyParameter); + } + + var produces = Responses.Where(r => r.Value.Content != null).SelectMany(r => r.Value.Content?.Keys).Distinct(); + if (produces.Count() > 0) + { + writer.WritePropertyName("produces"); + writer.WriteStartArray(); + foreach (var mediaType in produces) + { + writer.WriteValue(mediaType); + } + writer.WriteEndArray(); + } + + writer.WriteList("parameters", parameters, (w, p) => p.WriteAsV2(w)); + writer.WriteMap("responses", Responses, (w, r) => r.WriteAsV2(w)); + writer.WriteBoolProperty("deprecated", Deprecated, OpenApiOperation.DeprecatedDefault); + writer.WriteList("security", Security, (w, s) => s.WriteAsV2(w)); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index fbaf227e0..86e6b023f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -54,5 +55,90 @@ public bool Required public string Example { get; set; } public IDictionary Content { get; set; } public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + writer.WriteStringProperty("name", Name); + writer.WriteStringProperty("in", In.ToString()); + writer.WriteStringProperty("description", Description); + writer.WriteBoolProperty("required", Required, false); + writer.WriteBoolProperty("deprecated", Deprecated, false); + writer.WriteBoolProperty("allowEmptyValue", AllowEmptyValue, false); + writer.WriteStringProperty("style", Style); + writer.WriteBoolProperty("explode", Explode, false); + writer.WriteBoolProperty("allowReserved", AllowReserved, false); + writer.WriteObject("schema", Schema, (w, s) => s.WriteAsV3(w)); + writer.WriteList("examples", Examples, (w, e) => e.WriteAsV3(w)); + writer.WriteObject("example", Example, (w, s) => w.WriteRaw(s)); + writer.WriteMap("content", Content, (w, c) => c.WriteAsV3(w)); + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + return; + } + else + { + writer.WriteStartObject(); + writer.WriteStringProperty("name", Name); + if (this is BodyParameter) + { + writer.WriteStringProperty("in", "body"); // form? + } + else + { + writer.WriteStringProperty("in", In.ToString()); + } + writer.WriteStringProperty("description", Description); + writer.WriteBoolProperty("required", Required, false); + writer.WriteBoolProperty("deprecated", Deprecated, false); + writer.WriteBoolProperty("allowEmptyValue", AllowEmptyValue, false); + + writer.WriteBoolProperty("allowReserved", AllowReserved, false); + if (this is BodyParameter) + { + writer.WriteObject("schema", Schema, (w, s) => s.WriteAsV2(w)); + } + else + { + Schema.SerializeSchemaProperties(writer); + } + // writer.WriteList("examples", Examples, AnyNode.Write); + // writer.WriteObject("example", Example, AnyNode.Write); + writer.WriteEndObject(); + } + } + } + + internal class BodyParameter : OpenApiParameter + { } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs index c47aae2ab..34e3bcf3d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs @@ -8,6 +8,7 @@ using System.Linq; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -43,5 +44,73 @@ public void AddOperation(OperationType operationType, OpenApiOperation operation this.operations.Add(operationType.GetOperationTypeName(), operation); } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("summary", Summary); + writer.WriteStringProperty("description", Description); + if (Parameters != null && Parameters.Count > 0) + { + writer.WritePropertyName("parameters"); + writer.WriteStartArray(); + foreach (var parameter in Parameters) + { + parameter.WriteAsV3(writer); + } + writer.WriteEndArray(); + + } + writer.WriteList("servers", Servers, (w, s) => s.WriteAsV3(w)); + + foreach (var operationPair in Operations) + { + writer.WritePropertyName(operationPair.Key); + operationPair.Value.WriteAsV3(writer); + } + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("x-summary", Summary); + writer.WriteStringProperty("x-description", Description); + if (Parameters != null && Parameters.Count > 0) + { + writer.WritePropertyName("parameters"); + writer.WriteStartArray(); + foreach (var parameter in Parameters) + { + parameter.WriteAsV2(writer); + } + writer.WriteEndArray(); + + } + //writer.WriteList("x-servers", Servers, WriteServer); + + foreach (var operationPair in Operations) + { + writer.WritePropertyName(operationPair.Key); + operationPair.Value.WriteAsV2(writer); + } + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs index 73b12c307..b95bb9eaf 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -88,5 +89,43 @@ IEnumerator> IEnumerable + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + //writer.WriteStartObject(); + foreach (var pathItem in this) + { + writer.WritePropertyName(pathItem.Key); + pathItem.Value.WriteAsV3(writer); + } + //writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + //writer.WriteStartObject(); + foreach (var pathItem in this) + { + writer.WritePropertyName(pathItem.Key); + pathItem.Value.WriteAsV2(writer); + } + //writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiReference.cs b/src/Microsoft.OpenApi/Models/OpenApiReference.cs index 5d6a2a63a..aa178183a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiReference.cs @@ -3,8 +3,9 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -using Microsoft.OpenApi.Interfaces; using System; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -131,5 +132,21 @@ public JsonPointer GetLocalPointer() { return new JsonPointer("#/components/" + GetReferenceTypeName(this.ReferenceType) + "/" + TypeName); } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + // nothing here + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index 17d57a543..d31ce921a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -21,5 +22,39 @@ public class OpenApiRequestBody : IOpenApiReference, IOpenApiExtension public Boolean Required { get; set; } public IDictionary Content { get; set; } public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + + writer.WriteStringProperty("description", Description); + writer.WriteBoolProperty("required", Required, false); + writer.WriteMap("content", Content, (w, c) => c.WriteAsV3(w)); + + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 41060137f..1eb9132a7 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -4,9 +4,11 @@ // ------------------------------------------------------------ using System; +using System.Linq; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -36,5 +38,77 @@ public void CreateContent(string mediatype, Action configure) Content.Add(mediatype, m); } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + + writer.WriteStringProperty("description", Description); + writer.WriteMap("content", Content, (w, c) => c.WriteAsV3(w)); + + writer.WriteMap("headers", Headers, (w, h) => h.WriteAsV3(w)); + writer.WriteMap("links", Links, (w, l) => l.WriteAsV3(w)); + + //Links + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + + writer.WriteStringProperty("description", Description); + if (Content != null) + { + var mediatype = Content.FirstOrDefault(); + if (mediatype.Value != null) + { + + writer.WriteObject("schema", mediatype.Value.Schema, (w, s) => s.WriteAsV2(w)); + + if (mediatype.Value.Example != null) + { + writer.WritePropertyName("examples"); + writer.WriteStartObject(); + writer.WritePropertyName(mediatype.Key); + writer.WriteValue(mediatype.Value.Example); + writer.WriteEndObject(); + } + } + } + writer.WriteMap("headers", Headers, (w, h) => h.WriteAsV2(w)); + + writer.WriteEndObject(); + } + } } } \ No newline at end of file diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 4efcca869..df0724f04 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -65,5 +66,165 @@ public OpenApiReference Pointer get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + + writer.WriteStringProperty("title", Title); + writer.WriteStringProperty("type", Type); + writer.WriteStringProperty("format", Format); + writer.WriteStringProperty("description", Description); + + writer.WriteNumberProperty("maxLength", MaxLength); + writer.WriteNumberProperty("minLength", MinLength); + writer.WriteStringProperty("pattern", Pattern); + writer.WriteStringProperty("default", Default); + + writer.WriteList("required", Required, (nodeWriter, s) => nodeWriter.WriteValue(s)); + + writer.WriteNumberProperty("maximum", Maximum); + writer.WriteBoolProperty("exclusiveMaximum", ExclusiveMaximum, false); + writer.WriteNumberProperty("minimum", Minimum); + writer.WriteBoolProperty("exclusiveMinimum", ExclusiveMinimum, false); + + if (AdditionalProperties != null) + { + writer.WritePropertyName("additionalProperties"); + AdditionalProperties.WriteAsV3(writer); + } + + if (Items != null) + { + writer.WritePropertyName("items"); + Items.WriteAsV3(writer); + } + writer.WriteNumberProperty("maxItems", MaxItems); + writer.WriteNumberProperty("minItems", MinItems); + + if (Properties != null) + { + writer.WritePropertyName("properties"); + writer.WriteStartObject(); + foreach (var prop in Properties) + { + writer.WritePropertyName(prop.Key); + if (prop.Value != null) + { + prop.Value.WriteAsV3(writer); + } + else + { + writer.WriteValue("null"); + } + } + writer.WriteEndObject(); + } + writer.WriteNumberProperty("maxProperties", MaxProperties); + writer.WriteNumberProperty("minProperties", MinProperties); + + writer.WriteList("enum", Enum, (nodeWriter, s) => nodeWriter.WriteValue(s)); + + writer.WriteEndObject(); + } + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + if (this.IsReference()) + { + this.WriteRef(writer); + } + else + { + writer.WriteStartObject(); + SerializeSchemaProperties(writer); + writer.WriteEndObject(); + } + } + + public void SerializeSchemaProperties(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStringProperty("title", Title); + writer.WriteStringProperty("type", Type); + writer.WriteStringProperty("format", Format); + writer.WriteStringProperty("description", Description); + + writer.WriteNumberProperty("maxLength", MaxLength); + writer.WriteNumberProperty("minLength", MinLength); + writer.WriteStringProperty("pattern", Pattern); + writer.WriteStringProperty("default", Default); + + writer.WriteList("required", Required, (nodeWriter, s) => nodeWriter.WriteValue(s)); + + writer.WriteNumberProperty("maximum", Maximum); + writer.WriteBoolProperty("exclusiveMaximum", ExclusiveMaximum, false); + writer.WriteNumberProperty("minimum", Minimum); + writer.WriteBoolProperty("exclusiveMinimum", ExclusiveMinimum, false); + + if (AdditionalProperties != null) + { + writer.WritePropertyName("additionalProperties"); + AdditionalProperties.WriteAsV2(writer); + } + + if (Items != null) + { + writer.WritePropertyName("items"); + Items.WriteAsV2(writer); + } + writer.WriteNumberProperty("maxItems", MaxItems); + writer.WriteNumberProperty("minItems", MinItems); + + if (Properties != null) + { + writer.WritePropertyName("properties"); + writer.WriteStartObject(); + foreach (var prop in Properties) + { + writer.WritePropertyName(prop.Key); + if (prop.Value != null) + { + prop.Value.WriteAsV2(writer); + } + else + { + writer.WriteValue("null"); + } + } + writer.WriteEndObject(); + } + writer.WriteNumberProperty("maxProperties", MaxProperties); + writer.WriteNumberProperty("minProperties", MinProperties); + + writer.WriteList("enum", Enum, (nodeWriter, s) => nodeWriter.WriteValue(s)); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs index c335fc4e4..f4a327166 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -14,5 +15,64 @@ namespace Microsoft.OpenApi.Models public class OpenApiSecurityRequirement : IOpenApiElement { public Dictionary> Schemes { get; set; } = new Dictionary>(); + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + + foreach (var scheme in Schemes) + { + writer.WritePropertyName(scheme.Key.Pointer.TypeName); + if (scheme.Value.Count > 0) + { + writer.WriteStartArray(); + foreach (var scope in scheme.Value) + { + writer.WriteValue(scope); + } + writer.WriteEndArray(); + } + else + { + writer.WriteValue("[]"); + } + } + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + + foreach (var scheme in Schemes) + { + writer.WritePropertyName(scheme.Key.Pointer.TypeName); + writer.WriteStartArray(); + + foreach (var scope in scheme.Value) + { + writer.WriteValue(scope); + } + + writer.WriteEndArray(); + } + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index 9228241e7..d23efb3c2 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -64,5 +65,100 @@ public OpenApiReference Pointer { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("type", Type.ToString()); + switch (Type) + { + case SecuritySchemeTypeKind.http: + writer.WriteStringProperty("scheme", Scheme); + writer.WriteStringProperty("bearerFormat", BearerFormat); + break; + case SecuritySchemeTypeKind.oauth2: + //writer.WriteStringProperty("scheme", this.Scheme); + //TODO: + case SecuritySchemeTypeKind.apiKey: + writer.WriteStringProperty("in", In.ToString()); + writer.WriteStringProperty("name", Name); + + break; + } + + writer.WriteObject("flows", Flows, (w, o) => o.WriteAsV3(w)); + + writer.WriteStringProperty("openIdConnectUrl", OpenIdConnectUrl?.ToString()); + + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + if (Type == SecuritySchemeTypeKind.http) + { + if (Scheme == "basic") + { + writer.WriteStringProperty("type", "basic"); + } + } + else + { + writer.WriteStringProperty("type", Type.ToString()); + } + switch (Type) + { + case SecuritySchemeTypeKind.oauth2: + //writer.WriteStringProperty("scheme", this.Scheme); + //TODO: + case SecuritySchemeTypeKind.apiKey: + writer.WriteStringProperty("in", In.ToString()); + writer.WriteStringProperty("name", Name); + + break; + } + + if (Flows != null) + { + if (Flows.Implicit != null) + { + writer.WriteStringProperty("flow", "implicit"); + Flows.Implicit.WriteAsV2(writer); + } + else if (Flows.Password != null) + { + writer.WriteStringProperty("flow", "password"); + Flows.Password.WriteAsV2(writer); + } + else if (Flows.ClientCredentials != null) + { + writer.WriteStringProperty("flow", "application"); + Flows.ClientCredentials.WriteAsV2(writer); + } + else if (Flows.AuthorizationCode != null) + { + writer.WriteStringProperty("flow", "accessCode"); + Flows.AuthorizationCode.WriteAsV2(writer); + } + } + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiServer.cs b/src/Microsoft.OpenApi/Models/OpenApiServer.cs index e09d57ff5..a372cf221 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiServer.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiServer.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -19,5 +20,30 @@ public class OpenApiServer : IOpenApiExtension public IDictionary Variables { get; set; } = new Dictionary(); public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("url", Url); + writer.WriteStringProperty("description", Description); + writer.WriteMap("variables", Variables, (w, v) => v.WriteAsV3(w)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs b/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs index 7279936f2..ac4573f87 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -19,5 +20,30 @@ public class OpenApiServerVariable : IOpenApiExtension public List Enum { get; set; } = new List(); public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("default", Default); + writer.WriteStringProperty("description", Description); + writer.WriteList("enum", Enum, (w, s) => w.WriteValue(s)); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiTag.cs b/src/Microsoft.OpenApi/Models/OpenApiTag.cs index a45ef431c..835e7233c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiTag.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiTag.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -38,5 +39,37 @@ OpenApiReference IOpenApiReference.Pointer { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("name", Name); + writer.WriteStringProperty("description", Description); + writer.WriteEndObject(); + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + writer.WriteStringProperty("name", Name); + writer.WriteStringProperty("description", Description); + writer.WriteEndObject(); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiXml.cs b/src/Microsoft.OpenApi/Models/OpenApiXml.cs index ae14331e3..8df4e1eea 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiXml.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiXml.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models { @@ -46,5 +47,21 @@ public class OpenApiXml : IOpenApiExtension /// Specification Extensions. /// public IDictionary Extensions { get; set; } + + /// + /// Serialize to Open Api v3.0 + /// + public virtual void WriteAsV3(IOpenApiWriter writer) + { + // nothing here + } + + /// + /// Serialize to Open Api v2.0 + /// + public virtual void WriteAsV2(IOpenApiWriter writer) + { + // nothing here + } } } diff --git a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs new file mode 100644 index 000000000..1e63c20a2 --- /dev/null +++ b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs @@ -0,0 +1,96 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.IO; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; + +namespace Microsoft.OpenApi +{ + /// + /// Represents the Open Api serializer. + /// + public static class OpenApiElementSerializeExtensions + { + /// + /// Serialize the to the given stream as JSON. + /// + /// the + /// The Open Api element. + /// The output stream. + /// The Open Api specification version, default is 3.0. + public static void SerializeAsJson(this T element, Stream stream, + OpenApiSpecVersion specVersion = OpenApiSpecVersion.OpenApi3_0) + where T : IOpenApiElement + { + element.Serialize(stream, specVersion, OpenApiFormat.Json); + } + + /// + /// Serialize the to the given stream as YAML. + /// + /// the + /// The Open Api element. + /// The output stream. + /// The Open Api specification version, default is 3.0. + public static void SerializeAsYaml(this T element, Stream stream, + OpenApiSpecVersion specVersion = OpenApiSpecVersion.OpenApi3_0) + where T : IOpenApiElement + { + element.Serialize(stream, specVersion, OpenApiFormat.Yaml); + } + + /// + /// Serialize the to the given stream. + /// + /// the + /// The Open Api element. + /// The given stream. + /// The Open Api specification version. + /// The output format (JSON or YAML). + public static void Serialize(this T element, Stream stream, OpenApiSpecVersion specVersion, OpenApiFormat format) + where T : IOpenApiElement + { + if (element == null) + { + throw Error.ArgumentNull(nameof(element)); + } + + if (stream == null) + { + throw Error.ArgumentNull(nameof(stream)); + } + + IOpenApiWriter writer; + switch (format) + { + case OpenApiFormat.Json: + writer = new OpenApiJsonWriter(new StreamWriter(stream)); + break; + case OpenApiFormat.Yaml: + writer = new OpenApiYamlWriter(new StreamWriter(stream)); + break; + default: + throw new OpenApiException("Not supported Open Api document format!"); + } + + switch (specVersion) + { + case OpenApiSpecVersion.OpenApi3_0: + element.WriteAsV3(writer); + break; + + case OpenApiSpecVersion.OpenApi2_0: + element.WriteAsV2(writer); + break; + + default: + throw new OpenApiException("Unknown Open API specification version."); + } + + writer.Flush(); + } + } +} diff --git a/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs index 9a2b15eee..502e2e20e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs @@ -29,7 +29,7 @@ public void EmptyTest() private static JObject ExportV2ToJObject(OpenApiDocument openApiDoc) { var outputStream = new MemoryStream(); - openApiDoc.Save(outputStream, new OpenApiV2Writer(s => new OpenApiJsonWriter(new StreamWriter(s)))); + openApiDoc.SerializeAsJson(outputStream, OpenApiSpecVersion.OpenApi2_0); outputStream.Position = 0; var json = new StreamReader(outputStream).ReadToEnd(); var jObject = JObject.Parse(json); @@ -57,7 +57,7 @@ public void SimpleTest() var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); var outputStream = new MemoryStream(); - openApiDoc.Save(outputStream, new OpenApiV2Writer()); + openApiDoc.SerializeAsJson(outputStream, OpenApiSpecVersion.OpenApi2_0); } [Fact] diff --git a/test/Microsoft.OpenApi.Tests/ExampleTests.cs b/test/Microsoft.OpenApi.Tests/ExampleTests.cs index 498d390cc..14b0ac48a 100644 --- a/test/Microsoft.OpenApi.Tests/ExampleTests.cs +++ b/test/Microsoft.OpenApi.Tests/ExampleTests.cs @@ -7,7 +7,6 @@ using System; using System.IO; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Writers; using Xunit; namespace Microsoft.OpenApi.Tests @@ -39,7 +38,7 @@ public void WriteResponseExample() }))); var stream = new MemoryStream(); - doc.Save(stream); + doc.SerializeAsJson(stream); stream.Position = 0; var yamlStream = new YamlStream(); diff --git a/test/Microsoft.OpenApi.Tests/Serialization/OpenApiExternalDocsExtensionsTests.cs b/test/Microsoft.OpenApi.Tests/Serialization/OpenApiExternalDocsExtensionsTests.cs new file mode 100644 index 000000000..44aebc32b --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Serialization/OpenApiExternalDocsExtensionsTests.cs @@ -0,0 +1,74 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using Microsoft.OpenApi.Models; +using Xunit; +using System.IO; + +namespace Microsoft.OpenApi.Serialization.Tests +{ + public class OpenApiExternalDocsExtensionsTests + { + public static OpenApiExternalDocs BasicExDocs = new OpenApiExternalDocs(); + public static OpenApiExternalDocs AdvanceExDocs = new OpenApiExternalDocs() + { + Url = new Uri("https://example.com"), + Description = "Find more info here" + }; + + #region OpenAPI V3 + [Theory] + [InlineData(OpenApiFormat.Json, "{ }")] + [InlineData(OpenApiFormat.Yaml, "")] + public void SerializeBasicExternalDocsAsV3Works(OpenApiFormat format, string expect) + { + // Arrange & Act + MemoryStream stream = new MemoryStream(); + string actual = BasicExDocs.Serialize(OpenApiSpecVersion.OpenApi3_0, format); + + // Assert + Assert.Equal(expect, actual); + } + + [Fact] + public void SerializeAdvanceExDocssAsV3JsonWorks() + { + // Arrange + string expect = @" +{ + ""description"": ""Find more info here"", + ""url"": ""https://example.com"" +}"; + + // Act + string actual = AdvanceExDocs.SerializeAsJson(); + + // Assert + Assert.Equal(expect, actual); + } + + [Fact] + public void SerializeAdvanceExDocssAsV3YamlWorks() + { + // Arrange + string expect = @" +description: Find more info here +url: https://example.com"; + + // Act + string actual = AdvanceExDocs.SerializeAsYaml(); + + // Assert + Assert.Equal(expect, actual); + } + + #endregion + + #region OpenAPI V2 + + #endregion + } +} diff --git a/test/Microsoft.OpenApi.Tests/Serialization/OpenApiSerializerTestHelper.cs b/test/Microsoft.OpenApi.Tests/Serialization/OpenApiSerializerTestHelper.cs new file mode 100644 index 000000000..3df744f1d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Serialization/OpenApiSerializerTestHelper.cs @@ -0,0 +1,52 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.IO; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Serialization.Tests +{ + public static class OpenApiSerializerTestHelper + { + public static string SerializeAsJson(this T element, + OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0) + where T : IOpenApiElement + { + return element.Serialize(version, OpenApiFormat.Json); + } + + public static string SerializeAsYaml(this T element, + OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0) + where T : IOpenApiElement + { + return element.Serialize(version, OpenApiFormat.Yaml); + } + + public static string Serialize(this T element, + OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0, + OpenApiFormat format = OpenApiFormat.Json) + where T : IOpenApiElement + { + if (element == null) + { + throw Error.ArgumentNull(nameof(element)); + } + + MemoryStream stream = new MemoryStream(); + element.Serialize(stream, version, format); + stream.Position = 0; + string value = new StreamReader(stream).ReadToEnd(); + + if (value.IndexOf("\n") == -1) + { + return value; + } + else + { + return "\r\n" + value.Replace("\n", "\r\n"); + } + } + } +} From a6ee229524af9e6a7ab2825207f07da6357e7a5f Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Fri, 27 Oct 2017 14:10:15 -0700 Subject: [PATCH 02/13] arrange the test files into correct folder --- .../Microsoft.OpenApi.Tests.csproj | 7 +- .../{ => Models}/OpenApiDocumentTests.cs | 2 +- .../Models/OpenApiExternalDocsTests.cs | 73 +++++++++++++++++++ .../Models/OpenApiSerializerTestHelper.cs | 52 +++++++++++++ .../{ => Models}/OpenApiTagTests.cs | 4 +- .../OpenApiExternalDocsTests.cs | 20 ----- 6 files changed, 131 insertions(+), 27 deletions(-) rename test/Microsoft.OpenApi.Tests/{ => Models}/OpenApiDocumentTests.cs (92%) create mode 100644 test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs create mode 100644 test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs rename test/Microsoft.OpenApi.Tests/{ => Models}/OpenApiTagTests.cs (90%) delete mode 100644 test/Microsoft.OpenApi.Tests/OpenApiExternalDocsTests.cs diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index f1eb26f3b..3d57aa727 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -43,9 +43,10 @@ - - - + + + + diff --git a/test/Microsoft.OpenApi.Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs similarity index 92% rename from test/Microsoft.OpenApi.Tests/OpenApiDocumentTests.cs rename to test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 36f43d882..68f0603cd 100644 --- a/test/Microsoft.OpenApi.Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -5,7 +5,7 @@ using Microsoft.OpenApi.Models; -namespace Microsoft.OpenApi.Tests +namespace Microsoft.OpenApi.Models.Tests { public class OpenApiDocumentTests { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs new file mode 100644 index 000000000..16d90609c --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs @@ -0,0 +1,73 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using Xunit; +using System.IO; + +namespace Microsoft.OpenApi.Models.Tests +{ + public class OpenApiExternalDocsTests + { + public static OpenApiExternalDocs BasicExDocs = new OpenApiExternalDocs(); + public static OpenApiExternalDocs AdvanceExDocs = new OpenApiExternalDocs() + { + Url = new Uri("https://example.com"), + Description = "Find more info here" + }; + + #region OpenAPI V3 + [Theory] + [InlineData(OpenApiFormat.Json, "{ }")] + [InlineData(OpenApiFormat.Yaml, "")] + public void SerializeBasicExternalDocsAsV3Works(OpenApiFormat format, string expect) + { + // Arrange & Act + MemoryStream stream = new MemoryStream(); + string actual = BasicExDocs.Serialize(OpenApiSpecVersion.OpenApi3_0, format); + + // Assert + Assert.Equal(expect, actual); + } + + [Fact] + public void SerializeAdvanceExDocssAsV3JsonWorks() + { + // Arrange + string expect = @" +{ + ""description"": ""Find more info here"", + ""url"": ""https://example.com"" +}"; + + // Act + string actual = AdvanceExDocs.SerializeAsJson(); + + // Assert + Assert.Equal(expect, actual); + } + + [Fact] + public void SerializeAdvanceExDocssAsV3YamlWorks() + { + // Arrange + string expect = @" +description: Find more info here +url: https://example.com"; + + // Act + string actual = AdvanceExDocs.SerializeAsYaml(); + + // Assert + Assert.Equal(expect, actual); + } + + #endregion + + #region OpenAPI V2 + + #endregion + } +} diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs new file mode 100644 index 000000000..5345cdbba --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs @@ -0,0 +1,52 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.IO; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Tests +{ + public static class OpenApiSerializerTestHelper + { + public static string SerializeAsJson(this T element, + OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0) + where T : IOpenApiElement + { + return element.Serialize(version, OpenApiFormat.Json); + } + + public static string SerializeAsYaml(this T element, + OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0) + where T : IOpenApiElement + { + return element.Serialize(version, OpenApiFormat.Yaml); + } + + public static string Serialize(this T element, + OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0, + OpenApiFormat format = OpenApiFormat.Json) + where T : IOpenApiElement + { + if (element == null) + { + throw Error.ArgumentNull(nameof(element)); + } + + MemoryStream stream = new MemoryStream(); + element.Serialize(stream, version, format); + stream.Position = 0; + string value = new StreamReader(stream).ReadToEnd(); + + if (value.IndexOf("\n") == -1) + { + return value; + } + else + { + return "\r\n" + value.Replace("\n", "\r\n"); + } + } + } +} diff --git a/test/Microsoft.OpenApi.Tests/OpenApiTagTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs similarity index 90% rename from test/Microsoft.OpenApi.Tests/OpenApiTagTests.cs rename to test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs index c349f881c..b038bc812 100644 --- a/test/Microsoft.OpenApi.Tests/OpenApiTagTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs @@ -3,9 +3,7 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Tests +namespace Microsoft.OpenApi.Models.Tests { public class OpenApiTagTests { diff --git a/test/Microsoft.OpenApi.Tests/OpenApiExternalDocsTests.cs b/test/Microsoft.OpenApi.Tests/OpenApiExternalDocsTests.cs deleted file mode 100644 index 0c97a5c65..000000000 --- a/test/Microsoft.OpenApi.Tests/OpenApiExternalDocsTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System; -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Tests -{ - public class OpenApiExternalDocsTests - { - public static OpenApiExternalDocs BasicExDocs = new OpenApiExternalDocs(); - public static OpenApiExternalDocs AdvanceExDocs = new OpenApiExternalDocs() - { - Url = new Uri("https://example.com"), - Description = "Find more info here" - }; - } -} From 20f5d4786f5cdc4f129ad39a42b9f917eeaad982 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Fri, 27 Oct 2017 15:20:07 -0700 Subject: [PATCH 03/13] Add OpenApiConstant.cs and add the Unit test for OpenApiContact --- .../Models/OpenApiConstants.cs | 196 ++++++++++++++++++ .../Models/OpenApiContact.cs | 16 +- .../Microsoft.OpenApi.Tests.csproj | 5 +- .../Models/OpenApiContactTests.cs | 83 ++++++++ .../Models/OpenApiExternalDocsTests.cs | 5 +- 5 files changed, 297 insertions(+), 8 deletions(-) create mode 100644 src/Microsoft.OpenApi/Models/OpenApiConstants.cs create mode 100644 test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs new file mode 100644 index 000000000..ca8d7123f --- /dev/null +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -0,0 +1,196 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +namespace Microsoft.OpenApi.Models +{ + internal static class OpenApiConstants + { + public const string OpenApiDocOpenApi = "openapi"; + + public const string OpenApiDocInfo = "info"; + + public const string OpenApiDocTitle = "title"; + + public const string OpenApiDocType = "type"; + + public const string OpenApiDocFormat = "format"; + + public const string OpenApiDocVersion = "version"; + + public const string OpenApiDocContact = "contact"; + + public const string OpenApiDocLicense = "license"; + + public const string OpenApiDocTermsOfService = "termsOfService"; + + public const string OpenApiDocServers = "servers"; + + public const string OpenApiDocServer = "server"; + + public const string OpenApiDocPaths = "paths"; + + public const string OpenApiDocComponents = "components"; + + public const string OpenApiDocSecurity = "security"; + + public const string OpenApiDocTags = "tags"; + + public const string OpenApiDocExternalDocs = "externalDocs"; + + public const string OpenApiDocOperationRef = "operationRef"; + + public const string OpenApiDocOperationId = "operationId"; + + public const string OpenApiDocParameters = "parameters"; + + public const string OpenApiDocRequestBody = "requestBody"; + + public const string OpenApiDocExtensionFieldNamePrefix = "x-"; + + public const string OpenApiDocName = "name"; + + public const string OpenApiDocIn = "in"; + + public const string OpenApiDocSummary = "summary"; + + public const string OpenApiDocVariables = "variables"; + + public const string OpenApiDocDescription = "description"; + + public const string OpenApiDocRequired = "required"; + + public const string OpenApiDocDeprecated = "deprecated"; + + public const string OpenApiDocStyle = "style"; + + public const string OpenApiDocExplode = "explode"; + + public const string OpenApiDocAllowReserved = "allowReserved"; + + public const string OpenApiDocSchema = "schema"; + + public const string OpenApiDocSchemas = "schemas"; + + public const string OpenApiDocResponses = "responses"; + + public const string OpenApiDocExample = "example"; + + public const string OpenApiDocExamples = "examples"; + + public const string OpenApiDocEncoding = "encoding"; + + public const string OpenApiDocRequestBodies = "requestBodies"; + + public const string OpenApiDocAllowEmptyValue = "allowEmptyValue"; + + public const string OpenApiDocValue = "value"; + + public const string OpenApiDocExternalValue = "externalValue"; + + public const string OpenApiDocDollarRef = "$ref"; + + public const string OpenApiDocHeaders = "headers"; + + public const string OpenApiDocSecuritySchemes = "securitySchemes"; + + public const string OpenApiDocContent = "content"; + + public const string OpenApiDocLinks = "links"; + + public const string OpenApiDocCallbacks = "callbacks"; + + public const string OpenApiDocUrl = "url"; + + public const string OpenApiDocEmail = "email"; + + public const string OpenApiDocDefault = "default"; + + public const string OpenApiDocEnum = "enum"; + + public const string OpenApiDocMultipleOf = "multipleOf"; + + public const string OpenApiDocMaximum = "maximum"; + + public const string OpenApiDocExclusiveMaximum = "exclusiveMaximum"; + + public const string OpenApiDocMinimum = "minimum"; + + public const string OpenApiDocExclusiveMinimum = "exclusiveMinimum"; + + public const string OpenApiDocMaxLength = "maxLength"; + + public const string OpenApiDocMinLength = "minLength"; + + public const string OpenApiDocPattern = "pattern"; + + public const string OpenApiDocMaxItems = "maxItems"; + + public const string OpenApiDocMinItems = "minItems"; + + public const string OpenApiDocUniqueItems = "uniqueItems"; + + public const string OpenApiDocMaxProperties = "maxProperties"; + + public const string OpenApiDocMinProperties = "minProperties"; + + public const string OpenApiDocAllOf = "allOf"; + + public const string OpenApiDocOneOf = "oneOf"; + + public const string OpenApiDocAnyOf = "anyOf"; + + public const string OpenApiDocNot = "not"; + + public const string OpenApiDocItems = "items"; + + public const string OpenApiDocProperties = "properties"; + + public const string OpenApiDocAdditionalProperties = "additionalProperties"; + + public const string OpenApiDocNullable = "nullable"; + + public const string OpenApiDocDiscriminator = "discriminator"; + + public const string OpenApiDocReadOnly = "readOnly"; + + public const string OpenApiDocWriteOnly = "writeOnly"; + + public const string OpenApiDocXml = "xml"; + + public const string OpenApiDocImplicit = "implicit"; + + public const string OpenApiDocPassword = "password"; + + public const string OpenApiDocClientCredentials = "clientCredentials"; + + public const string OpenApiDocAuthorizationCode = "authorizationCode"; + + public const string OpenApiDocAuthorizationUrl = "authorizationUrl"; + + public const string OpenApiDocTokenUrl = "tokenUrl"; + + public const string OpenApiDocRefreshUrl = "refreshUrl"; + + public const string OpenApiDocScopes = "scopes"; + + public const string OpenApiDocContentType = "contentType"; + + public const string OpenApiDocGet = "get"; + + public const string OpenApiDocPut = "put"; + + public const string OpenApiDocPost = "post"; + + public const string OpenApiDocDelete = "delete"; + + public const string OpenApiDocOptions = "options"; + + public const string OpenApiDocHead = "head"; + + public const string OpenApiDocPatch = "patch"; + + public const string OpenApiDocTrace = "trace"; + } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiContact.cs b/src/Microsoft.OpenApi/Models/OpenApiContact.cs index ae96ed1e7..abd5501e9 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiContact.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiContact.cs @@ -61,9 +61,19 @@ private void WriteInternal(IOpenApiWriter writer) } writer.WriteStartObject(); - writer.WriteStringProperty("name", Name); - writer.WriteStringProperty("url", Url?.OriginalString); - writer.WriteStringProperty("email", Email); + + // name + writer.WriteStringProperty(OpenApiConstants.OpenApiDocName, Name); + + // url + writer.WriteStringProperty(OpenApiConstants.OpenApiDocUrl, Url?.OriginalString); + + // email + writer.WriteStringProperty(OpenApiConstants.OpenApiDocEmail, Email); + + // extensions + writer.WriteExtensions(Extensions); + writer.WriteEndObject(); } } diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 3d57aa727..8e75acb25 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -43,6 +43,9 @@ + + + @@ -50,8 +53,6 @@ - - diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs new file mode 100644 index 000000000..36aecd9c2 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs @@ -0,0 +1,83 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using System.IO; +using System.Collections.Generic; +using Microsoft.OpenApi.Any; +using Xunit; + +namespace Microsoft.OpenApi.Models.Tests +{ + public class OpenApiContactTests + { + public static OpenApiContact BasicContact = new OpenApiContact(); + public static OpenApiContact AdvanceContact = new OpenApiContact() + { + Name = "API Support", + Url = new Uri("http://www.example.com/support"), + Email = "support@example.com", + Extensions = new Dictionary + { + { "x-internal-id", new OpenApiInteger(42) } + } + }; + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json, "{ }")] + [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json, "{ }")] + [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml, "")] + [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml, "")] + public void SerializeBasicContactWorks(OpenApiSpecVersion version, + OpenApiFormat format, string expect) + { + // Arrange & Act + string actual = BasicContact.Serialize(version, format); + + // Assert + Assert.Equal(expect, actual); + } + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi3_0)] + [InlineData(OpenApiSpecVersion.OpenApi2_0)] + public void SerializeAdvanceContactAsJsonWorks(OpenApiSpecVersion version) + { + // Arrange + string expect = @" +{ + ""name"": ""API Support"", + ""url"": ""http://www.example.com/support"", + ""email"": ""support@example.com"", + ""x-internal-id"": 42 +}"; + + // Act + string actual = AdvanceContact.SerializeAsJson(version); + + // Assert + Assert.Equal(expect, actual); + } + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi3_0)] + [InlineData(OpenApiSpecVersion.OpenApi2_0)] + public void SerializeAdvanceContactAsYamlWorks(OpenApiSpecVersion version) + { + // Arrange + string expect = @" +name: API Support +url: http://www.example.com/support +email: support@example.com +x-internal-id: 42"; + + // Act + string actual = AdvanceContact.SerializeAsYaml(version); + + // Assert + Assert.Equal(expect, actual); + } + } +} diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs index 16d90609c..9c55103d3 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs @@ -25,7 +25,6 @@ public class OpenApiExternalDocsTests public void SerializeBasicExternalDocsAsV3Works(OpenApiFormat format, string expect) { // Arrange & Act - MemoryStream stream = new MemoryStream(); string actual = BasicExDocs.Serialize(OpenApiSpecVersion.OpenApi3_0, format); // Assert @@ -33,7 +32,7 @@ public void SerializeBasicExternalDocsAsV3Works(OpenApiFormat format, string exp } [Fact] - public void SerializeAdvanceExDocssAsV3JsonWorks() + public void SerializeAdvanceExDocsAsV3JsonWorks() { // Arrange string expect = @" @@ -50,7 +49,7 @@ public void SerializeAdvanceExDocssAsV3JsonWorks() } [Fact] - public void SerializeAdvanceExDocssAsV3YamlWorks() + public void SerializeAdvanceExDocsAsV3YamlWorks() { // Arrange string expect = @" From 7b48c9914d114d2bb1cb2473bf0be6eff5b7a2e0 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Fri, 27 Oct 2017 16:36:38 -0700 Subject: [PATCH 04/13] Modify and add test for OpenApiInfo, OpenApiLicense --- .../YamlReaders/OpenApiV2Deserializer.cs | 2 +- .../YamlReaders/OpenApiV3Deserializer.cs | 2 +- .../Models/OpenApiConstants.cs | 14 ++ src/Microsoft.OpenApi/Models/OpenApiInfo.cs | 70 ++++---- .../Models/OpenApiLicense.cs | 14 +- .../Writers/OpenApiV2Writer.cs | 2 +- .../Writers/OpenApiV3Writer.cs | 2 +- .../InfoTests.cs | 2 +- .../Microsoft.OpenApi.Tests.csproj | 2 + .../Models/OpenApiInfoTests.cs | 160 ++++++++++++++++++ .../Models/OpenApiLicenseTests.cs | 95 +++++++++++ 11 files changed, 328 insertions(+), 37 deletions(-) create mode 100644 test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs create mode 100644 test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Deserializer.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Deserializer.cs index f0c06c652..9361a1a47 100644 --- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Deserializer.cs +++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Deserializer.cs @@ -83,7 +83,7 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) { { "title", (o,n) => { o.Title = n.GetScalarValue(); } }, { "description", (o,n) => { o.Description = n.GetScalarValue(); } }, - { "termsOfService", (o,n) => { o.TermsOfService = n.GetScalarValue(); } }, + { "termsOfService", (o,n) => { o.TermsOfService = new Uri(n.GetScalarValue()); } }, { "contact", (o,n) => { o.Contact = LoadContact(n); } }, { "license", (o,n) => { o.License = LoadLicense(n); } }, { "version", (o,n) => { o.Version = new Version(n.GetScalarValue()); } } diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs index 589d0392b..30623b2fb 100644 --- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs +++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs @@ -57,7 +57,7 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) { "title", (o,n) => { o.Title = n.GetScalarValue(); } }, { "version", (o,n) => { o.Version = new Version(n.GetScalarValue()); } }, { "description", (o,n) => { o.Description = n.GetScalarValue(); } }, - { "termsOfService", (o,n) => { o.TermsOfService = n.GetScalarValue(); } }, + { "termsOfService", (o,n) => { o.TermsOfService = new Uri(n.GetScalarValue()); } }, { "contact", (o,n) => { o.Contact = LoadContact(n); } }, { "license", (o,n) => { o.License = LoadLicense(n); } } }; diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs index ca8d7123f..37c67ef1d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -3,6 +3,8 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using System; + namespace Microsoft.OpenApi.Models { internal static class OpenApiConstants @@ -192,5 +194,17 @@ internal static class OpenApiConstants public const string OpenApiDocPatch = "patch"; public const string OpenApiDocTrace = "trace"; + + public const string OpenApiDocDefaultName = "Default Name"; + + public const string OpenApiDocDefaultDefault = "Default Default"; + + public const string OpenApiDocDefaultTitle = "Default Title"; + + public static Version OpenApiDocDefaultVersion = new Version(3, 0, 0); + + public static Uri OpenApiDocDefaultUrl = new Uri("http://localhost/"); + + public const string OpenApiDocDefaultDescription = "Default Description"; } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs index 1efaf72fc..744eb397c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs @@ -20,7 +20,7 @@ public class OpenApiInfo : IOpenApiExtension /// /// REQUIRED. The title of the application. /// - public string Title { get; set; } = "[Title Required]"; + public string Title { get; set; } = OpenApiConstants.OpenApiDocDefaultTitle; /// /// A short description of the application. @@ -35,19 +35,7 @@ public class OpenApiInfo : IOpenApiExtension /// /// A URL to the Terms of Service for the API. MUST be in the format of a URL. /// - public string TermsOfService - { - get { return this.termsOfService; } - set - { - if (!Uri.IsWellFormedUriString(value, UriKind.RelativeOrAbsolute)) - { - throw new OpenApiException("`info.termsOfService` MUST be a URL"); - }; - this.termsOfService = value; - } - } - string termsOfService; + public Uri TermsOfService { get; set; } /// /// The contact information for the exposed API. @@ -64,9 +52,6 @@ public string TermsOfService /// public IDictionary Extensions { get; set; } = new Dictionary(); - private static Regex versionRegex = new Regex(@"\d+\.\d+\.\d+"); - - /// /// Serialize to Open Api v3.0 /// @@ -78,12 +63,28 @@ public virtual void WriteAsV3(IOpenApiWriter writer) } writer.WriteStartObject(); - writer.WriteStringProperty("title", Title); - writer.WriteStringProperty("description", Description); - writer.WriteStringProperty("termsOfService", TermsOfService); - writer.WriteObject("contact", Contact, (w, c) => c.WriteAsV3(w)); - writer.WriteObject("license", License, (w, l) => l.WriteAsV3(w)); - writer.WriteStringProperty("version", Version.ToString()); + + // title + writer.WriteStringProperty(OpenApiConstants.OpenApiDocTitle, Title); + + // description + writer.WriteStringProperty(OpenApiConstants.OpenApiDocDescription, Description); + + // termsOfService + writer.WriteStringProperty(OpenApiConstants.OpenApiDocTermsOfService, TermsOfService?.OriginalString); + + // contact object + writer.WriteObject(OpenApiConstants.OpenApiDocContact, Contact, (w, c) => c.WriteAsV3(w)); + + // license object + writer.WriteObject(OpenApiConstants.OpenApiDocLicense, License, (w, l) => l.WriteAsV3(w)); + + // version + writer.WriteStringProperty(OpenApiConstants.OpenApiDocVersion, Version?.ToString()); + + // specification extensions + writer.WriteExtensions(Extensions); + writer.WriteEndObject(); } @@ -98,17 +99,28 @@ public virtual void WriteAsV2(IOpenApiWriter writer) } writer.WriteStartObject(); - writer.WriteStringProperty("title", Title); - writer.WriteStringProperty("description", Description); + // title + writer.WriteStringProperty(OpenApiConstants.OpenApiDocTitle, Title); + + // description + writer.WriteStringProperty(OpenApiConstants.OpenApiDocDescription, Description); + + // termsOfService + writer.WriteStringProperty(OpenApiConstants.OpenApiDocTermsOfService, TermsOfService?.OriginalString); + + // contact object + writer.WriteObject(OpenApiConstants.OpenApiDocContact, Contact, (w, c) => c.WriteAsV2(w)); - writer.WriteStringProperty("termsOfService", TermsOfService); + // license object + writer.WriteObject(OpenApiConstants.OpenApiDocLicense, License, (w, l) => l.WriteAsV2(w)); - writer.WriteObject("contact", Contact, (w, c) => c.WriteAsV2(w)); + // version + writer.WriteStringProperty(OpenApiConstants.OpenApiDocVersion, Version?.ToString()); - writer.WriteObject("license", License, (w, l) => l.WriteAsV2(w)); + // specification extensions + writer.WriteExtensions(Extensions); - writer.WriteStringProperty("version", Version.ToString()); writer.WriteEndObject(); } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs index 9da656565..bbeded0d3 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs @@ -19,7 +19,7 @@ public class OpenApiLicense : IOpenApiExtension // /// REQUIRED.The license name used for the API. /// - public string Name { get; set; } + public string Name { get; set; } = OpenApiConstants.OpenApiDocDefaultName; /// /// The URL pointing to the contact information. MUST be in the format of a URL. @@ -55,8 +55,16 @@ private void WriteInternal(IOpenApiWriter writer) } writer.WriteStartObject(); - writer.WriteStringProperty("name", Name); - writer.WriteStringProperty("url", Url?.OriginalString); + + // name + writer.WriteStringProperty(OpenApiConstants.OpenApiDocName, Name); + + // url + writer.WriteStringProperty(OpenApiConstants.OpenApiDocUrl, Url?.OriginalString); + + // specification extensions + writer.WriteExtensions(Extensions); + writer.WriteEndObject(); } } diff --git a/src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs b/src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs index f9d0d6d8b..548ff8c29 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs @@ -85,7 +85,7 @@ public static void WriteInfo(IOpenApiWriter writer, OpenApiInfo info) writer.WriteStringProperty("title", info.Title); writer.WriteStringProperty("description", info.Description); - writer.WriteStringProperty("termsOfService", info.TermsOfService); + writer.WriteStringProperty("termsOfService", info.TermsOfService.OriginalString); writer.WriteObject("contact", info.Contact, WriteContact); writer.WriteObject("license", info.License, WriteLicense); writer.WriteStringProperty("version", info.Version.ToString()); diff --git a/src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs b/src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs index c13a806e2..2ddc5bd4f 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs @@ -65,7 +65,7 @@ public static void WriteInfo(IOpenApiWriter writer, OpenApiInfo info) writer.WriteStringProperty("title", info.Title); writer.WriteStringProperty("description", info.Description); - writer.WriteStringProperty("termsOfService", info.TermsOfService); + writer.WriteStringProperty("termsOfService", info.TermsOfService.OriginalString); writer.WriteObject("contact", info.Contact, WriteContact); writer.WriteObject("license", info.License, WriteLicense); writer.WriteStringProperty("version", info.Version.ToString()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs index 7ffb2d9fb..259c116b8 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs @@ -38,7 +38,7 @@ public void ParseCompleteHeaderOpenApi() Assert.Equal("The Api", openApiDoc.Info.Title); Assert.Equal("0.9.1", openApiDoc.Info.Version.ToString()); Assert.Equal("This is an api", openApiDoc.Info.Description); - Assert.Equal("http://example.org/Dowhatyouwant", openApiDoc.Info.TermsOfService); + Assert.Equal("http://example.org/Dowhatyouwant", openApiDoc.Info.TermsOfService.OriginalString); Assert.Equal("Darrel Miller", openApiDoc.Info.Contact.Name); // Assert.Equal("@darrel_miller", openApiDoc.Info.Contact.Extensions["x-twitter"].GetValueNode().GetScalarValue()); } diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 8e75acb25..e356be32d 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -45,6 +45,8 @@ + + diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs new file mode 100644 index 000000000..75c29ab64 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiInfoTests.cs @@ -0,0 +1,160 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using Microsoft.OpenApi.Any; +using Xunit; + +namespace Microsoft.OpenApi.Models.Tests +{ + public class OpenApiInfoTests + { + public static OpenApiInfo BasicInfo = new OpenApiInfo(); + public static OpenApiInfo AdvanceInfo = new OpenApiInfo() + { + Title = "Sample Pet Store App", + Description = "This is a sample server for a pet store.", + TermsOfService = new Uri("http://example.com/terms/"), + Contact = OpenApiContactTests.AdvanceContact, + License = OpenApiLicenseTests.AdvanceLicense, + Version = new Version(1, 1, 1), + Extensions = new Dictionary + { + { "x-updated", new OpenApiString("metadata") } + } + }; + + public static IEnumerable BasicInfoJsonExpect() + { + var specVersions = new[] { OpenApiSpecVersion.OpenApi3_0, OpenApiSpecVersion.OpenApi2_0 }; + foreach (var specVersion in specVersions) + { + yield return new object[] + { + specVersion, @" +{ + ""title"": ""Default Title"", + ""version"": ""1.0"" +}" + }; + } + } + + [Theory] + [MemberData(nameof(BasicInfoJsonExpect))] + public void SerializeBasicInfoAsJsonWorks(OpenApiSpecVersion version, string expect) + { + // Arrange & Act + string actual = BasicInfo.SerializeAsJson(version); + + // Assert + Assert.Equal(expect, actual); + } + + public static IEnumerable BasicInfoYamlExpect() + { + var specVersions = new[] { OpenApiSpecVersion.OpenApi3_0, OpenApiSpecVersion.OpenApi2_0 }; + foreach (var specVersion in specVersions) + { + yield return new object[] + { + specVersion, @" +title: Default Title +version: 1.0" + }; + } + } + + [Theory] + [MemberData(nameof(BasicInfoYamlExpect))] + public void SerializeBasicInfoAsYamlWorks(OpenApiSpecVersion version, string expect) + { + // Arrange & Act + string actual = BasicInfo.SerializeAsYaml(version); + + // Assert + Assert.Equal(expect, actual); + } + + public static IEnumerable AdvanceInfoJsonExpect() + { + var specVersions = new[] { OpenApiSpecVersion.OpenApi3_0, OpenApiSpecVersion.OpenApi2_0 }; + foreach (var specVersion in specVersions) + { + yield return new object[] + { + specVersion, @" +{ + ""title"": ""Sample Pet Store App"", + ""description"": ""This is a sample server for a pet store."", + ""termsOfService"": ""http://example.com/terms/"", + ""contact"": { + ""name"": ""API Support"", + ""url"": ""http://www.example.com/support"", + ""email"": ""support@example.com"", + ""x-internal-id"": 42 + }, + ""license"": { + ""name"": ""Apache 2.0"", + ""url"": ""http://www.apache.org/licenses/LICENSE-2.0.html"", + ""x-copyright"": ""Abc"" + }, + ""version"": ""1.1.1"", + ""x-updated"": ""metadata"" +}" + }; + } + } + + [Theory] + [MemberData(nameof(AdvanceInfoJsonExpect))] + public void SerializeAdvanceInfoAsJsonWorks(OpenApiSpecVersion version, string expect) + { + // Arrange & Act + string actual = AdvanceInfo.SerializeAsJson(version); + + // Assert + Assert.Equal(expect, actual); + } + + public static IEnumerable AdvanceInfoYamlExpect() + { + var specVersions = new[] { OpenApiSpecVersion.OpenApi3_0, OpenApiSpecVersion.OpenApi2_0 }; + foreach (var specVersion in specVersions) + { + yield return new object[] + { + specVersion, @" +title: Sample Pet Store App +description: This is a sample server for a pet store. +termsOfService: http://example.com/terms/ +contact: + name: API Support + url: http://www.example.com/support + email: support@example.com + x-internal-id: 42 +license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + x-copyright: Abc +version: 1.1.1 +x-updated: metadata" + }; + } + } + + [Theory] + [MemberData(nameof(AdvanceInfoYamlExpect))] + public void SerializeAdvanceInfoAsYamlWorks(OpenApiSpecVersion version, string expect) + { + // Arrange & Act + string actual = AdvanceInfo.SerializeAsYaml(version); + + // Assert + Assert.Equal(expect, actual); + } + } +} diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs new file mode 100644 index 000000000..f9f145629 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs @@ -0,0 +1,95 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using System.IO; +using System.Collections.Generic; +using Microsoft.OpenApi.Any; +using Xunit; + +namespace Microsoft.OpenApi.Models.Tests +{ + public class OpenApiLicenseTests + { + public static OpenApiLicense BasicLicense = new OpenApiLicense(); + public static OpenApiLicense AdvanceLicense = new OpenApiLicense() + { + Name = "Apache 2.0", + Url = new Uri("http://www.apache.org/licenses/LICENSE-2.0.html"), + Extensions = new Dictionary + { + { "x-copyright", new OpenApiString("Abc") } + } + }; + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi3_0)] + [InlineData(OpenApiSpecVersion.OpenApi2_0)] + public void SerializeBasicLicenseAsJsonWorks(OpenApiSpecVersion version) + { + // Arrange + string expect = @" +{ + ""name"": ""Default Name"" +}"; + + // Act + string actual = BasicLicense.SerializeAsJson(version); + + // Assert + Assert.Equal(expect, actual); + } + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi3_0)] + [InlineData(OpenApiSpecVersion.OpenApi2_0)] + public void SerializeBasicLicenseAsYamlWorks(OpenApiSpecVersion version) + { + // Arrange & Act + string actual = BasicLicense.SerializeAsYaml(version); + + // Assert + Assert.Equal("name: Default Name", actual); + } + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi3_0)] + [InlineData(OpenApiSpecVersion.OpenApi2_0)] + public void SerializeAdvanceLicenseAsJsonWorks(OpenApiSpecVersion version) + { + // Arrange + string expect = @" +{ + ""name"": ""Apache 2.0"", + ""url"": ""http://www.apache.org/licenses/LICENSE-2.0.html"", + ""x-copyright"": ""Abc"" +}"; + + // Act + string actual = AdvanceLicense.SerializeAsJson(version); + + // Assert + Assert.Equal(expect, actual); + } + + [Theory] + [InlineData(OpenApiSpecVersion.OpenApi3_0)] + [InlineData(OpenApiSpecVersion.OpenApi2_0)] + public void SerializeAdvanceLicenseAsYamlWorks(OpenApiSpecVersion version) + { + // Arrange + string expect = @" +name: Apache 2.0 +url: http://www.apache.org/licenses/LICENSE-2.0.html +x-copyright: Abc"; + + // Act + string actual = AdvanceLicense.SerializeAsYaml(version); + + // Assert + Assert.Equal(expect, actual); + } + } +} From 1b4632c352fd3a6aa7e507071762fce91281b085 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Fri, 27 Oct 2017 16:41:08 -0700 Subject: [PATCH 05/13] remove unused files (OpenApiSerializer, OpenApiV2(3)Writer, etc and codes --- src/Microsoft.OpenApi/OpenApiSerializer.cs | 107 ---- .../Writers/IOpenApiStructureWriter.cs | 21 - .../Writers/OpenApiSerializerBase.cs | 30 - .../Writers/OpenApiV2Serializer.cs | 44 -- .../Writers/OpenApiV2Writer.cs | 521 ---------------- .../Writers/OpenApiV3Serializer.cs | 44 -- .../Writers/OpenApiV3Writer.cs | 560 ------------------ .../Writers/OpenApiWriterExtensions.cs | 12 - 8 files changed, 1339 deletions(-) delete mode 100644 src/Microsoft.OpenApi/OpenApiSerializer.cs delete mode 100644 src/Microsoft.OpenApi/Writers/IOpenApiStructureWriter.cs delete mode 100644 src/Microsoft.OpenApi/Writers/OpenApiSerializerBase.cs delete mode 100644 src/Microsoft.OpenApi/Writers/OpenApiV2Serializer.cs delete mode 100644 src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs delete mode 100644 src/Microsoft.OpenApi/Writers/OpenApiV3Serializer.cs delete mode 100644 src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs diff --git a/src/Microsoft.OpenApi/OpenApiSerializer.cs b/src/Microsoft.OpenApi/OpenApiSerializer.cs deleted file mode 100644 index fb276c1da..000000000 --- a/src/Microsoft.OpenApi/OpenApiSerializer.cs +++ /dev/null @@ -1,107 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System.IO; -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Writers; - -namespace Microsoft.OpenApi -{ - /// - /// Represents the Open Api serializer. - /// - public class OpenApiSerializer - { - /// - /// The Open Api serializer settings. - /// - public OpenApiSerializerSettings Settings { get; } - - /// - /// Initializes a new instance of the class. - /// - public OpenApiSerializer() - : this(new OpenApiSerializerSettings()) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The write setting. - public OpenApiSerializer(OpenApiSerializerSettings settings) - { - Settings = settings ?? throw Error.ArgumentNull(nameof(settings)); - } - - /// - /// Serialize the to the given stream. - /// - /// The given stream. - /// The given - public virtual void Serialize(Stream stream, OpenApiDocument document) - { - if (stream == null) - { - throw Error.ArgumentNull(nameof(stream)); - } - - if (document == null) - { - throw Error.ArgumentNull(nameof(document)); - } - - IOpenApiWriter writer; - switch (Settings.Format) - { - case OpenApiFormat.Json: - writer = new OpenApiJsonWriter(new StreamWriter(stream)); - break; - case OpenApiFormat.Yaml: - writer = new OpenApiYamlWriter(new StreamWriter(stream)); - break; - default: - throw new OpenApiException("Not supported Open Api document format!"); - } - - Serialize(writer, document); - } - - /// - /// Serialize the using the given writer . - /// - /// The given writer. - /// The given - public virtual void Serialize(IOpenApiWriter writer, OpenApiDocument document) - { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - - if (document == null) - { - throw Error.ArgumentNull(nameof(document)); - } - - OpenApiSerializerBase serializer; - switch(Settings.SpecVersion) - { - case OpenApiSpecVersion.OpenApi3_0: - serializer = new OpenApiV3Serializer(Settings); - break; - - case OpenApiSpecVersion.OpenApi2_0: - serializer = new OpenApiV2Serializer(Settings); - break; - - default: - throw new OpenApiException("Unknown Open API specification version."); - } - - serializer.Write(writer, document); - } - } -} diff --git a/src/Microsoft.OpenApi/Writers/IOpenApiStructureWriter.cs b/src/Microsoft.OpenApi/Writers/IOpenApiStructureWriter.cs deleted file mode 100644 index 6a6277b2f..000000000 --- a/src/Microsoft.OpenApi/Writers/IOpenApiStructureWriter.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System.IO; -using Microsoft.OpenApi; -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Writers -{ - public interface IOpenApiStructureWriter - { - void Write(Stream stream, OpenApiDocument document); - } - - public interface IOpenApiDocumentSerializer - { - bool Save(OpenApiDocument document); - } -} diff --git a/src/Microsoft.OpenApi/Writers/OpenApiSerializerBase.cs b/src/Microsoft.OpenApi/Writers/OpenApiSerializerBase.cs deleted file mode 100644 index ec8ebbc8b..000000000 --- a/src/Microsoft.OpenApi/Writers/OpenApiSerializerBase.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Writers -{ - /// - /// Base class for Open API document internal serializer. - /// - internal abstract class OpenApiSerializerBase - { - public OpenApiSerializerSettings Settings { get; } - - public OpenApiSerializerBase(OpenApiSerializerSettings settings) - { - Settings = settings; - } - - /// - /// Abstract method to write the Open Api document. - /// - /// The Open API document. - /// The Open Api writer. - /// True for successful, false for errors. - public abstract void Write(IOpenApiWriter writer, OpenApiDocument document); - } -} diff --git a/src/Microsoft.OpenApi/Writers/OpenApiV2Serializer.cs b/src/Microsoft.OpenApi/Writers/OpenApiV2Serializer.cs deleted file mode 100644 index ee6d0a5c8..000000000 --- a/src/Microsoft.OpenApi/Writers/OpenApiV2Serializer.cs +++ /dev/null @@ -1,44 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Writers -{ - /// - /// Class to serialize Open API v2.0 document. - /// - internal class OpenApiV2Serializer : OpenApiSerializerBase - { - /// - /// Initializes a new instance of the class. - /// - public OpenApiV2Serializer(OpenApiSerializerSettings settings) - : base(settings) - { - } - - /// - /// Write the Open Api document to v2.0. - /// - /// The Open API document. - /// The Open Api writer. - /// True for successful, false for errors. - public override void Write(IOpenApiWriter writer, OpenApiDocument document) - { - if (document == null) - { - throw Error.ArgumentNull(nameof(document)); - } - - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - - // add the logic to write v2.0 document. - } - } -} diff --git a/src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs b/src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs deleted file mode 100644 index 548ff8c29..000000000 --- a/src/Microsoft.OpenApi/Writers/OpenApiV2Writer.cs +++ /dev/null @@ -1,521 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System; -using System.IO; -using System.Linq; -using System.Collections.Generic; -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Writers -{ - public class OpenApiV2Writer : IOpenApiStructureWriter - { - Func defaultWriterFactory = s => new OpenApiYamlWriter(new StreamWriter(s)); - Func writerFactory; - - public OpenApiV2Writer(Func writerFactory = null) - { - this.writerFactory = writerFactory ?? defaultWriterFactory; - } - - public void Write(Stream stream, OpenApiDocument document) - { - - var writer = writerFactory(stream); - // writer.WriteStartDocument(); - WriteOpenApiDocument(writer, document); - // writer.WriteEndDocument(); - writer.Flush(); - } - - public static void WriteOpenApiDocument(IOpenApiWriter writer, OpenApiDocument doc) - { - writer.WriteStartObject(); - - writer.WritePropertyName("swagger"); - writer.WriteValue("2.0"); - - writer.WriteObject("info", doc.Info, WriteInfo); - WriteHostInfo(writer, doc.Servers); - - writer.WritePropertyName("paths"); - - writer.WriteStartObject(); - WritePaths(writer, doc.Paths); - writer.WriteEndObject(); - - writer.WriteList("tags", doc.Tags, WriteTag); - if (!doc.Components.IsEmpty()) - { - WriteComponents(writer, doc.Components); - } - if (doc.ExternalDocs.Url != null) - { - writer.WriteObject("externalDocs", doc.ExternalDocs, WriteExternalDocs); - } - writer.WriteList("security", doc.SecurityRequirements, WriteSecurityRequirement); - - writer.WriteEndObject(); - - } - - private static void WriteHostInfo(IOpenApiWriter writer, IList servers) - { - if (servers == null || servers.Count == 0) return; - var firstServer = servers.First(); - var url = new Uri(firstServer.Url); - writer.WriteStringProperty("host", url.GetComponents(UriComponents.Host | UriComponents.Port, UriFormat.SafeUnescaped)); - writer.WriteStringProperty("basePath", url.AbsolutePath); - var schemes = servers.Select(s => new Uri(s.Url).Scheme).Distinct(); - writer.WritePropertyName("schemes"); - writer.WriteStartArray(); - foreach(var scheme in schemes) - { - writer.WriteValue(scheme); - } - writer.WriteEndArray(); - } - - public static void WriteInfo(IOpenApiWriter writer, OpenApiInfo info) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("title", info.Title); - writer.WriteStringProperty("description", info.Description); - writer.WriteStringProperty("termsOfService", info.TermsOfService.OriginalString); - writer.WriteObject("contact", info.Contact, WriteContact); - writer.WriteObject("license", info.License, WriteLicense); - writer.WriteStringProperty("version", info.Version.ToString()); - - writer.WriteEndObject(); - } - - public static void WriteContact(IOpenApiWriter writer, OpenApiContact contact) - { - - writer.WriteStartObject(); - - writer.WriteStringProperty("name", contact.Name); - writer.WriteStringProperty("url", contact.Url?.OriginalString); - writer.WriteStringProperty("email", contact.Email); - - writer.WriteEndObject(); - } - - public static void WriteLicense(IOpenApiWriter writer, OpenApiLicense license) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("name", license.Name); - writer.WriteStringProperty("url", license.Url?.OriginalString); - - writer.WriteEndObject(); - } - public static void WriteTag(IOpenApiWriter writer, OpenApiTag tag) - { - writer.WriteStartObject(); - writer.WriteStringProperty("name", tag.Name); - writer.WriteStringProperty("description", tag.Description); - writer.WriteEndObject(); - } - - public static void WriteTagRef(IOpenApiWriter writer, OpenApiTag tag) - { - writer.WriteValue(tag.Name); - } - public static void WriteComponents(IOpenApiWriter writer, OpenApiComponents components) - { - writer.WriteMap("definitions", components.Schemas, WriteSchema); - writer.WriteMap("responses", components.Responses, WriteResponse); - writer.WriteMap("parameters", components.Parameters, WriteParameter); - writer.WriteMap("securityDefinitions", components.SecuritySchemes, WriteSecurityScheme); - - } - - public static void WriteExternalDocs(IOpenApiWriter writer, OpenApiExternalDocs externalDocs) - { - writer.WriteStartObject(); - writer.WriteStringProperty("description", externalDocs.Description); - writer.WriteStringProperty("url", externalDocs.Url?.OriginalString); - writer.WriteEndObject(); - } - - - public static void WriteSecurityRequirement(IOpenApiWriter writer, OpenApiSecurityRequirement securityRequirement) - { - - writer.WriteStartObject(); - - foreach (var scheme in securityRequirement.Schemes) - { - - writer.WritePropertyName(scheme.Key.Pointer.TypeName); - writer.WriteStartArray(); - - foreach (var scope in scheme.Value) - { - writer.WriteValue(scope); - } - - writer.WriteEndArray(); - } - - writer.WriteEndObject(); - } - - - public static void WritePaths(IOpenApiWriter writer, OpenApiPaths paths) - { - foreach (var pathItem in paths) - { - writer.WritePropertyName(pathItem.Key); - WritePathItem(writer, pathItem.Value); - } - } - - public static void WritePathItem(IOpenApiWriter writer, OpenApiPathItem pathItem) - { - writer.WriteStartObject(); - writer.WriteStringProperty("x-summary", pathItem.Summary); - writer.WriteStringProperty("x-description", pathItem.Description); - if (pathItem.Parameters != null && pathItem.Parameters.Count > 0) - { - writer.WritePropertyName("parameters"); - writer.WriteStartArray(); - foreach (var parameter in pathItem.Parameters) - { - WriteParameter(writer, parameter); - } - writer.WriteEndArray(); - - } - //writer.WriteList("x-servers", pathItem.Servers, WriteServer); - - foreach (var operationPair in pathItem.Operations) - { - writer.WritePropertyName(operationPair.Key); - WriteOperation(writer, operationPair.Value); - } - writer.WriteEndObject(); - } - - - public static void WriteOperation(IOpenApiWriter writer, OpenApiOperation operation) - { - writer.WriteStartObject(); - writer.WriteList("tags", operation.Tags, WriteTagRef); - writer.WriteStringProperty("summary", operation.Summary); - writer.WriteStringProperty("description", operation.Description); - writer.WriteObject("externalDocs", operation.ExternalDocs, WriteExternalDocs); - - writer.WriteStringProperty("operationId", operation.OperationId); - - var parameters = new List(operation.Parameters); - - OpenApiParameter bodyParameter = null; - if (operation.RequestBody != null) - { - writer.WritePropertyName("consumes"); - writer.WriteStartArray(); - var consumes = operation.RequestBody.Content.Keys.Distinct(); - foreach (var mediaType in consumes) - { - writer.WriteValue(mediaType); - } - writer.WriteEndArray(); - - // Create bodyParameter - bodyParameter = new BodyParameter() - { - Name = "body", - Description = operation.RequestBody.Description, - Schema = operation.RequestBody.Content.First().Value.Schema - }; - // add to parameters - parameters.Add(bodyParameter); - } - - var produces = operation.Responses.Where(r => r.Value.Content != null).SelectMany(r => r.Value.Content?.Keys).Distinct(); - if (produces.Count() > 0) - { - writer.WritePropertyName("produces"); - writer.WriteStartArray(); - foreach (var mediaType in produces) - { - writer.WriteValue(mediaType); - } - writer.WriteEndArray(); - } - - writer.WriteList("parameters", parameters, WriteParameterOrReference); - writer.WriteMap("responses", operation.Responses, WriteResponseOrReference); - writer.WriteBoolProperty("deprecated", operation.Deprecated, OpenApiOperation.DeprecatedDefault); - writer.WriteList("security", operation.Security, WriteSecurityRequirement); - - writer.WriteEndObject(); - } - - public static void WriteParameterOrReference(IOpenApiWriter writer, OpenApiParameter parameter) - { - if (parameter.IsReference()) - { - parameter.WriteRef(writer); - return; - } - else - { - WriteParameter(writer, parameter); - } - } - public static void WriteParameter(IOpenApiWriter writer, OpenApiParameter parameter) - { - writer.WriteStartObject(); - writer.WriteStringProperty("name", parameter.Name); - if (parameter is BodyParameter) - { - writer.WriteStringProperty("in", "body"); // form? - } - else - { - writer.WriteStringProperty("in", parameter.In.ToString()); - } - writer.WriteStringProperty("description", parameter.Description); - writer.WriteBoolProperty("required", parameter.Required, false); - writer.WriteBoolProperty("deprecated", parameter.Deprecated, false); - writer.WriteBoolProperty("allowEmptyValue", parameter.AllowEmptyValue, false); - - writer.WriteBoolProperty("allowReserved", parameter.AllowReserved, false); - if (parameter is BodyParameter) - { - writer.WriteObject("schema", parameter.Schema, WriteSchemaOrReference); - } - else - { - WriteSchemaProperties(writer, parameter.Schema); - } -// writer.WriteList("examples", parameter.Examples, AnyNode.Write); -// writer.WriteObject("example", parameter.Example, AnyNode.Write); - writer.WriteEndObject(); - } - - - - public static void WriteResponseOrReference(IOpenApiWriter writer, OpenApiResponse response) - { - if (response.IsReference()) - { - response.WriteRef(writer); - } - else - { - WriteResponse(writer, response); - } - } - - public static void WriteResponse(IOpenApiWriter writer, OpenApiResponse response) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("description", response.Description); - if (response.Content != null) - { - var mediatype = response.Content.FirstOrDefault(); - if (mediatype.Value != null) - { - - writer.WriteObject("schema", mediatype.Value.Schema, WriteSchemaOrReference); - - if (mediatype.Value.Example != null) - { - writer.WritePropertyName("examples"); - writer.WriteStartObject(); - writer.WritePropertyName(mediatype.Key); - writer.WriteValue(mediatype.Value.Example); - writer.WriteEndObject(); - } - - } - - } - writer.WriteMap("headers", response.Headers, WriteHeaderOrReference); - - writer.WriteEndObject(); - } - - - public static void WriteSchemaOrReference(IOpenApiWriter writer, OpenApiSchema schema) - { - if (schema.IsReference()) - { - schema.WriteRef(writer); - } - else - { - WriteSchema(writer, schema); - } - } - - public static void WriteSchema(IOpenApiWriter writer, OpenApiSchema schema) - { - writer.WriteStartObject(); - - WriteSchemaProperties(writer, schema); - - writer.WriteEndObject(); - } - - private static void WriteSchemaProperties(IOpenApiWriter writer, OpenApiSchema schema) - { - writer.WriteStringProperty("title", schema.Title); - writer.WriteStringProperty("type", schema.Type); - writer.WriteStringProperty("format", schema.Format); - writer.WriteStringProperty("description", schema.Description); - - writer.WriteNumberProperty("maxLength", schema.MaxLength); - writer.WriteNumberProperty("minLength", schema.MinLength); - writer.WriteStringProperty("pattern", schema.Pattern); - writer.WriteStringProperty("default", schema.Default); - - writer.WriteList("required", schema.Required, (nodeWriter, s) => nodeWriter.WriteValue(s)); - - writer.WriteNumberProperty("maximum", schema.Maximum); - writer.WriteBoolProperty("exclusiveMaximum", schema.ExclusiveMaximum, false); - writer.WriteNumberProperty("minimum", schema.Minimum); - writer.WriteBoolProperty("exclusiveMinimum", schema.ExclusiveMinimum, false); - - if (schema.AdditionalProperties != null) - { - writer.WritePropertyName("additionalProperties"); - WriteSchemaOrReference(writer, schema.AdditionalProperties); - } - - if (schema.Items != null) - { - writer.WritePropertyName("items"); - WriteSchemaOrReference(writer, schema.Items); - } - writer.WriteNumberProperty("maxItems", schema.MaxItems); - writer.WriteNumberProperty("minItems", schema.MinItems); - - if (schema.Properties != null) - { - writer.WritePropertyName("properties"); - writer.WriteStartObject(); - foreach (var prop in schema.Properties) - { - writer.WritePropertyName(prop.Key); - if (prop.Value != null) - { - WriteSchemaOrReference(writer, prop.Value); - } - else - { - writer.WriteValue("null"); - } - } - writer.WriteEndObject(); - } - writer.WriteNumberProperty("maxProperties", schema.MaxProperties); - writer.WriteNumberProperty("minProperties", schema.MinProperties); - - writer.WriteList("enum", schema.Enum, (nodeWriter, s) => nodeWriter.WriteValue(s)); - } - - public static void WriteHeaderOrReference(IOpenApiWriter writer, OpenApiHeader header) - { - if (header.IsReference()) - { - header.WriteRef(writer); - } - else - { - WriteHeader(writer, header); - } - } - - public static void WriteHeader(IOpenApiWriter writer, OpenApiHeader header) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("description", header.Description); - writer.WriteBoolProperty("required", header.Required, false); - writer.WriteBoolProperty("deprecated", header.Deprecated, false); - writer.WriteBoolProperty("allowEmptyValue", header.AllowEmptyValue, false); - writer.WriteStringProperty("style", header.Style); - writer.WriteBoolProperty("explode", header.Explode, false); - writer.WriteBoolProperty("allowReserved", header.AllowReserved, false); - writer.WriteObject("schema", header.Schema, WriteSchema); - writer.WriteStringProperty("example", header.Example); - - writer.WriteEndObject(); - } - - public static void WriteSecurityScheme(IOpenApiWriter writer, OpenApiSecurityScheme securityScheme) - { - writer.WriteStartObject(); - if (securityScheme.Type == SecuritySchemeTypeKind.http) - { - if (securityScheme.Scheme == "basic") - { - writer.WriteStringProperty("type", "basic"); - } - } - else - { - writer.WriteStringProperty("type", securityScheme.Type.ToString()); - } - switch (securityScheme.Type) - { - case SecuritySchemeTypeKind.oauth2: - //writer.WriteStringProperty("scheme", this.Scheme); - //TODO: - case SecuritySchemeTypeKind.apiKey: - writer.WriteStringProperty("in", securityScheme.In.ToString()); - writer.WriteStringProperty("name", securityScheme.Name); - - break; - } - - if (securityScheme.Flows != null) - { - if (securityScheme.Flows.Implicit != null) - { - writer.WriteStringProperty("flow", "implicit"); - WriteOAuthFlow(writer, securityScheme.Flows.Implicit); - } - else if (securityScheme.Flows.Password != null) - { - writer.WriteStringProperty("flow", "password"); - WriteOAuthFlow(writer, securityScheme.Flows.Password); - } - else if (securityScheme.Flows.ClientCredentials != null) - { - writer.WriteStringProperty("flow", "application"); - WriteOAuthFlow(writer, securityScheme.Flows.ClientCredentials); - } - else if (securityScheme.Flows.AuthorizationCode != null) - { - writer.WriteStringProperty("flow", "accessCode"); - WriteOAuthFlow(writer, securityScheme.Flows.AuthorizationCode); - } - } - - writer.WriteEndObject(); - } - - private static void WriteOAuthFlow(IOpenApiWriter writer, OpenApiOAuthFlow oAuthFlow) - { - writer.WriteStringProperty("authorizationUrl", oAuthFlow.AuthorizationUrl?.ToString()); - writer.WriteStringProperty("tokenUrl", oAuthFlow.TokenUrl?.ToString()); - writer.WriteMap("scopes", oAuthFlow.Scopes, (w,s) => w.WriteValue(s)); - } - } - - internal class BodyParameter : OpenApiParameter - { - - } -} diff --git a/src/Microsoft.OpenApi/Writers/OpenApiV3Serializer.cs b/src/Microsoft.OpenApi/Writers/OpenApiV3Serializer.cs deleted file mode 100644 index 674b53ea4..000000000 --- a/src/Microsoft.OpenApi/Writers/OpenApiV3Serializer.cs +++ /dev/null @@ -1,44 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Writers -{ - /// - /// Class to serialize Open API v3.0 document. - /// - internal class OpenApiV3Serializer : OpenApiSerializerBase - { - /// - /// Initializes a new instance of the class. - /// - public OpenApiV3Serializer(OpenApiSerializerSettings settings) - : base(settings) - { - } - - /// - /// Write the Open Api document to v3.0. - /// - /// The Open API document. - /// The Open Api writer. - /// True for successful, false for errors. - public override void Write(IOpenApiWriter writer, OpenApiDocument document) - { - if (document == null) - { - throw Error.ArgumentNull(nameof(document)); - } - - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - - // add the logic to write v3.0 document. - } - } -} diff --git a/src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs b/src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs deleted file mode 100644 index 2ddc5bd4f..000000000 --- a/src/Microsoft.OpenApi/Writers/OpenApiV3Writer.cs +++ /dev/null @@ -1,560 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System; -using System.IO; -using Microsoft.OpenApi.Models; - -namespace Microsoft.OpenApi.Writers -{ - public class OpenApiV3Writer : IOpenApiStructureWriter - { - Func defaultWriterFactory = s => new OpenApiYamlWriter(new StreamWriter(s)); - Func writerFactory; - - public OpenApiV3Writer(Func writerFactory = null) - { - this.writerFactory = writerFactory ?? defaultWriterFactory; - } - - public void Write(Stream stream, OpenApiDocument document) - { - - var writer = writerFactory(stream); - // writer.WriteStartDocument(); - WriteOpenApiDocument(writer, document); - // writer.WriteEndDocument(); - writer.Flush(); - } - - public static void WriteOpenApiDocument(IOpenApiWriter writer, OpenApiDocument doc) - { - writer.WriteStartObject(); - - writer.WritePropertyName("openapi"); - writer.WriteValue("3.0.0"); - - writer.WriteObject("info", doc.Info, WriteInfo); - writer.WriteList("servers", doc.Servers, WriteServer); - writer.WritePropertyName("paths"); - - writer.WriteStartObject(); - WritePaths(writer, doc.Paths); - writer.WriteEndObject(); - - writer.WriteList("tags", doc.Tags, WriteTag); - if (!doc.Components.IsEmpty()) - { - writer.WriteObject("components", doc.Components, WriteComponents); - } - if (doc.ExternalDocs.Url != null) - { - writer.WriteObject("externalDocs", doc.ExternalDocs, WriteExternalDocs); - } - writer.WriteList("security", doc.SecurityRequirements, WriteSecurityRequirement); - - writer.WriteEndObject(); - - } - - public static void WriteInfo(IOpenApiWriter writer, OpenApiInfo info) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("title", info.Title); - writer.WriteStringProperty("description", info.Description); - writer.WriteStringProperty("termsOfService", info.TermsOfService.OriginalString); - writer.WriteObject("contact", info.Contact, WriteContact); - writer.WriteObject("license", info.License, WriteLicense); - writer.WriteStringProperty("version", info.Version.ToString()); - - writer.WriteEndObject(); - } - - public static void WriteContact(IOpenApiWriter writer, OpenApiContact contact) - { - - writer.WriteStartObject(); - - writer.WriteStringProperty("name", contact.Name); - writer.WriteStringProperty("url", contact.Url?.OriginalString); - writer.WriteStringProperty("email", contact.Email); - - writer.WriteEndObject(); - } - - public static void WriteLicense(IOpenApiWriter writer, OpenApiLicense license) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("name", license.Name); - writer.WriteStringProperty("url", license.Url?.OriginalString); - - writer.WriteEndObject(); - } - - public static void WriteServer(IOpenApiWriter writer, OpenApiServer server) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("url", server.Url); - writer.WriteStringProperty("description", server.Description); - - writer.WriteMap("variables", server.Variables, WriteServerVariable); - writer.WriteEndObject(); - } - - public static void WriteTag(IOpenApiWriter writer, OpenApiTag tag) - { - writer.WriteStartObject(); - writer.WriteStringProperty("name", tag.Name); - writer.WriteStringProperty("description", tag.Description); - writer.WriteEndObject(); - } - - public static void WriteTagRef(IOpenApiWriter writer, OpenApiTag tag) - { - writer.WriteValue(tag.Name); - } - - public static void WriteComponents(IOpenApiWriter writer, OpenApiComponents components) - { - writer.WriteStartObject(); - - writer.WriteMap("schemas", components.Schemas, WriteSchema); - writer.WriteMap("responses", components.Responses, WriteResponse); - writer.WriteMap("parameters", components.Parameters, WriteParameter); - writer.WriteMap("examples", components.Examples, WriteExample); - writer.WriteMap("requestBodies", components.RequestBodies, WriteRequestBody); - writer.WriteMap("headers", components.Headers, WriteHeader); - writer.WriteMap("securitySchemes", components.SecuritySchemes, WriteSecurityScheme); - writer.WriteMap("links", components.Links, WriteLink); - writer.WriteMap("callbacks", components.Callbacks, WriteCallback); - - writer.WriteEndObject(); - } - - public static void WriteServerVariable(IOpenApiWriter writer, OpenApiServerVariable variable) - { - writer.WriteStartObject(); - - writer.WriteList("enum", variable.Enum, (nodeWriter, s) => nodeWriter.WriteValue(s)); - writer.WriteStringProperty("default", variable.Default); - writer.WriteStringProperty("description", variable.Description); - - writer.WriteEndObject(); - - } - public static void WriteExternalDocs(IOpenApiWriter writer, OpenApiExternalDocs externalDocs) - { - writer.WriteStartObject(); - writer.WriteStringProperty("description", externalDocs.Description); - writer.WriteStringProperty("url", externalDocs.Url?.OriginalString); - writer.WriteEndObject(); - } - - - public static void WriteSecurityRequirement(IOpenApiWriter writer, OpenApiSecurityRequirement securityRequirement) - { - - writer.WriteStartObject(); - - foreach (var scheme in securityRequirement.Schemes) - { - - writer.WritePropertyName(scheme.Key.Pointer.TypeName); - if (scheme.Value.Count > 0) - { - writer.WriteStartArray(); - foreach (var scope in scheme.Value) - { - writer.WriteValue(scope); - } - writer.WriteEndArray(); - } - else - { - writer.WriteValue("[]"); - } - } - - writer.WriteEndObject(); - } - - - public static void WritePaths(IOpenApiWriter writer, OpenApiPaths paths) - { - - foreach (var pathItem in paths) - { - writer.WritePropertyName(pathItem.Key); - WritePathItem(writer, pathItem.Value); - } - } - - public static void WritePathItem(IOpenApiWriter writer, OpenApiPathItem pathItem) - { - writer.WriteStartObject(); - writer.WriteStringProperty("summary", pathItem.Summary); - writer.WriteStringProperty("description", pathItem.Description); - if (pathItem.Parameters != null && pathItem.Parameters.Count > 0) - { - writer.WritePropertyName("parameters"); - writer.WriteStartArray(); - foreach (var parameter in pathItem.Parameters) - { - WriteParameter(writer, parameter); - } - writer.WriteEndArray(); - - } - writer.WriteList("servers", pathItem.Servers, WriteServer); - - foreach (var operationPair in pathItem.Operations) - { - writer.WritePropertyName(operationPair.Key); - WriteOperation(writer, operationPair.Value); - } - writer.WriteEndObject(); - } - - - public static void WriteOperation(IOpenApiWriter writer, OpenApiOperation operation) - { - writer.WriteStartObject(); - writer.WriteList("tags", operation.Tags, WriteTagRef); - writer.WriteStringProperty("summary", operation.Summary); - writer.WriteStringProperty("description", operation.Description); - writer.WriteObject("externalDocs", operation.ExternalDocs, WriteExternalDocs); - - writer.WriteStringProperty("operationId", operation.OperationId); - writer.WriteList("parameters", operation.Parameters, WriteParameterOrReference); - writer.WriteObject("requestBody", operation.RequestBody, WriteRequestBodyOrReference); - writer.WriteMap("responses", operation.Responses, WriteResponseOrReference); - writer.WriteMap("callbacks", operation.Callbacks, WriteCallbackOrReference); - writer.WriteBoolProperty("deprecated", operation.Deprecated, OpenApiOperation.DeprecatedDefault); - writer.WriteList("security", operation.Security, WriteSecurityRequirement); - writer.WriteList("servers", operation.Servers, WriteServer); - - writer.WriteEndObject(); - } - - public static void WriteParameterOrReference(IOpenApiWriter writer, OpenApiParameter parameter) - { - if (parameter.IsReference()) - { - parameter.WriteRef(writer); - return; - } - else - { - WriteParameter(writer, parameter); - } - } - public static void WriteParameter(IOpenApiWriter writer, OpenApiParameter parameter) - { - writer.WriteStartObject(); - writer.WriteStringProperty("name", parameter.Name); - writer.WriteStringProperty("in", parameter.In.ToString()); - writer.WriteStringProperty("description", parameter.Description); - writer.WriteBoolProperty("required", parameter.Required, false); - writer.WriteBoolProperty("deprecated", parameter.Deprecated, false); - writer.WriteBoolProperty("allowEmptyValue", parameter.AllowEmptyValue, false); - writer.WriteStringProperty("style", parameter.Style); - writer.WriteBoolProperty("explode", parameter.Explode, false); - writer.WriteBoolProperty("allowReserved", parameter.AllowReserved, false); - writer.WriteObject("schema", parameter.Schema, WriteSchemaOrReference); - writer.WriteList("examples", parameter.Examples, WriteExample); - writer.WriteObject("example", parameter.Example, (w, s) => w.WriteRaw(s)); - writer.WriteMap("content", parameter.Content, WriteMediaType); - writer.WriteEndObject(); - } - - public static void WriteRequestBodyOrReference(IOpenApiWriter writer, OpenApiRequestBody requestBody) - { - if (requestBody.IsReference()) - { - requestBody.WriteRef(writer); - } - else - { - WriteRequestBody(writer, requestBody); - } - } - - public static void WriteRequestBody(IOpenApiWriter writer, OpenApiRequestBody requestBody) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("description", requestBody.Description); - writer.WriteBoolProperty("required", requestBody.Required, false); - writer.WriteMap("content", requestBody.Content, WriteMediaType); - - writer.WriteEndObject(); - } - - public static void WriteResponseOrReference(IOpenApiWriter writer, OpenApiResponse response) - { - if (response.IsReference()) - { - response.WriteRef(writer); - } - else - { - WriteResponse(writer, response); - } - } - - public static void WriteResponse(IOpenApiWriter writer, OpenApiResponse response) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("description", response.Description); - writer.WriteMap("content", response.Content, WriteMediaType); - - writer.WriteMap("headers", response.Headers, WriteHeaderOrReference); - writer.WriteMap("links", response.Links, WriteLinkOrReference); - - //Links - writer.WriteEndObject(); - } - - - public static void WriteSchemaOrReference(IOpenApiWriter writer, OpenApiSchema schema) - { - if (schema.IsReference()) - { - schema.WriteRef(writer); - } - else - { - WriteSchema(writer, schema); - } - } - - public static void WriteSchema(IOpenApiWriter writer, OpenApiSchema schema) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("title", schema.Title); - writer.WriteStringProperty("type", schema.Type); - writer.WriteStringProperty("format", schema.Format); - writer.WriteStringProperty("description", schema.Description); - - writer.WriteNumberProperty("maxLength", schema.MaxLength); - writer.WriteNumberProperty("minLength", schema.MinLength); - writer.WriteStringProperty("pattern", schema.Pattern); - writer.WriteStringProperty("default", schema.Default); - - writer.WriteList("required", schema.Required, (nodeWriter, s) => nodeWriter.WriteValue(s)); - - writer.WriteNumberProperty("maximum", schema.Maximum); - writer.WriteBoolProperty("exclusiveMaximum", schema.ExclusiveMaximum, false); - writer.WriteNumberProperty("minimum", schema.Minimum); - writer.WriteBoolProperty("exclusiveMinimum", schema.ExclusiveMinimum, false); - - if (schema.AdditionalProperties != null) - { - writer.WritePropertyName("additionalProperties"); - WriteSchemaOrReference(writer, schema.AdditionalProperties); - } - - if (schema.Items != null) - { - writer.WritePropertyName("items"); - WriteSchemaOrReference(writer, schema.Items); - } - writer.WriteNumberProperty("maxItems", schema.MaxItems); - writer.WriteNumberProperty("minItems", schema.MinItems); - - if (schema.Properties != null) - { - writer.WritePropertyName("properties"); - writer.WriteStartObject(); - foreach (var prop in schema.Properties) - { - writer.WritePropertyName(prop.Key); - if (prop.Value != null) - { - WriteSchemaOrReference(writer, prop.Value); - } - else - { - writer.WriteValue("null"); - } - } - writer.WriteEndObject(); - } - writer.WriteNumberProperty("maxProperties", schema.MaxProperties); - writer.WriteNumberProperty("minProperties", schema.MinProperties); - - writer.WriteList("enum", schema.Enum, (nodeWriter, s) => nodeWriter.WriteValue(s)); - - writer.WriteEndObject(); - } - - public static void WriteLinkOrReference(IOpenApiWriter writer, OpenApiLink link) - { - if (link.IsReference()) - { - link.WriteRef(writer); - } - else - { - WriteLink(writer, link); - } - } - - public static void WriteLink(IOpenApiWriter writer, OpenApiLink link) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("href", link.Href); - writer.WriteStringProperty("operationId", link.OperationId); - writer.WriteMap("parameters", link.Parameters, (w, x) => { w.WriteValue(x.ToString()); }); - - writer.WriteEndObject(); - } - - public static void WriteHeaderOrReference(IOpenApiWriter writer, OpenApiHeader header) - { - if (header.IsReference()) - { - header.WriteRef(writer); - } - else - { - WriteHeader(writer, header); - } - } - - public static void WriteHeader(IOpenApiWriter writer, OpenApiHeader header) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("description", header.Description); - writer.WriteBoolProperty("required", header.Required, false); - writer.WriteBoolProperty("deprecated", header.Deprecated, false); - writer.WriteBoolProperty("allowEmptyValue", header.AllowEmptyValue, false); - writer.WriteStringProperty("style", header.Style); - writer.WriteBoolProperty("explode", header.Explode, false); - writer.WriteBoolProperty("allowReserved", header.AllowReserved, false); - writer.WriteObject("schema", header.Schema, WriteSchema); - writer.WriteList("examples", header.Examples, WriteExampleOrReference); - writer.WriteObject("example", header.Example, (w, s) => w.WriteRaw(s)); - writer.WriteMap("content", header.Content, WriteMediaType); - - writer.WriteEndObject(); - } - - public static void WriteMediaType(IOpenApiWriter writer, OpenApiMediaType mediaType) - { - writer.WriteStartObject(); - - writer.WriteObject("schema", mediaType.Schema, WriteSchemaOrReference); - writer.WriteObject("example", mediaType.Example, (w, s) => w.WriteRaw(s)); - writer.WriteMap("examples", mediaType.Examples, WriteExampleOrReference); - - writer.WriteEndObject(); - } - - public static void WriteCallbackOrReference(IOpenApiWriter writer, OpenApiCallback callback) - { - if (callback.IsReference()) - { - callback.WriteRef(writer); - } - else - { - WriteCallback(writer, callback); - } - } - - public static void WriteCallback(IOpenApiWriter writer, OpenApiCallback callback) - { - writer.WriteStartObject(); - foreach (var item in callback.PathItems) - { - writer.WriteObject(item.Key.Expression, item.Value, WritePathItem); - } - writer.WriteEndObject(); - } - - public static void WriteExampleOrReference(IOpenApiWriter writer, OpenApiExample example) - { - if (example.IsReference()) - { - example.WriteRef(writer); - } - else - { - WriteExample(writer, example); - } - } - - public static void WriteExample(IOpenApiWriter writer, OpenApiExample example) - { - writer.WriteStartObject(); - writer.WriteStringProperty("summary", example.Summary); - writer.WriteStringProperty("description", example.Description); - if (example.Value != null) - { - writer.WritePropertyName("value"); - writer.WriteRaw(example.Value); - } - writer.WriteEndObject(); - } - - public static void WriteSecurityScheme(IOpenApiWriter writer, OpenApiSecurityScheme securityScheme) - { - writer.WriteStartObject(); - writer.WriteStringProperty("type", securityScheme.Type.ToString()); - switch (securityScheme.Type) - { - case SecuritySchemeTypeKind.http: - writer.WriteStringProperty("scheme", securityScheme.Scheme); - writer.WriteStringProperty("bearerFormat", securityScheme.BearerFormat); - break; - case SecuritySchemeTypeKind.oauth2: - //writer.WriteStringProperty("scheme", this.Scheme); - //TODO: - case SecuritySchemeTypeKind.apiKey: - writer.WriteStringProperty("in", securityScheme.In.ToString()); - writer.WriteStringProperty("name", securityScheme.Name); - - break; - } - - writer.WriteObject("flows", securityScheme.Flows, WriteOAuthFlows); - - writer.WriteStringProperty("openIdConnectUrl", securityScheme.OpenIdConnectUrl?.ToString()); - - writer.WriteEndObject(); - } - - public static void WriteOAuthFlows(IOpenApiWriter writer, OpenApiOAuthFlows oAuthFlows) - { - writer.WriteStartObject(); - - writer.WriteObject("implicit", oAuthFlows.Implicit, WriteOAuthFlow); - writer.WriteObject("password", oAuthFlows.Password, WriteOAuthFlow); - writer.WriteObject("clientCredentials", oAuthFlows.ClientCredentials, WriteOAuthFlow); - writer.WriteObject("authorizationCode", oAuthFlows.AuthorizationCode, WriteOAuthFlow); - - writer.WriteEndObject(); - } - - public static void WriteOAuthFlow(IOpenApiWriter writer, OpenApiOAuthFlow oAuthFlow) - { - writer.WriteStartObject(); - - writer.WriteStringProperty("authorizationUrl", oAuthFlow.AuthorizationUrl?.ToString()); - writer.WriteStringProperty("tokenUrl", oAuthFlow.TokenUrl?.ToString()); - writer.WriteStringProperty("refreshUrl", oAuthFlow.RefreshUrl?.ToString()); - writer.WriteMap("scopes", oAuthFlow.Scopes, (w, s) => w.WriteValue(s)); - writer.WriteEndObject(); - } - } -} diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs index 071150948..c5e2ee40a 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs @@ -5,10 +5,8 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Models; namespace Microsoft.OpenApi.Writers { @@ -17,16 +15,6 @@ namespace Microsoft.OpenApi.Writers /// public static class OpenApiWriterExtensions { - public static void Save(this OpenApiDocument doc, Stream stream, IOpenApiStructureWriter openApiWriter = null) - { - if (openApiWriter == null) - { - openApiWriter = new OpenApiV3Writer(); - } - - openApiWriter.Write(stream, doc); - } - public static void WriteObject(this IOpenApiWriter writer, string propertyName, T entity, Action parser) { if (entity == null) From 27a874271828c09f3b7075a286e343a11a17c725 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 15:02:41 -0700 Subject: [PATCH 06/13] rebase to the latest master codes --- .../OpenApiElementSerializeExtensions.cs | 34 +++++++++++++++---- .../Writers/OpenApiYamlWriter.cs | 5 ++- .../Models/OpenApiContactTests.cs | 4 +-- .../Models/OpenApiExternalDocsTests.cs | 2 +- .../StringExtensions.cs | 9 +++++ .../Writers/OpenApiYamlWriterTests.cs | 2 -- 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs index 1e63c20a2..ecdb951d2 100644 --- a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs +++ b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs @@ -14,29 +14,51 @@ namespace Microsoft.OpenApi /// public static class OpenApiElementSerializeExtensions { + /// + /// Serialize the to the given stream as JSON (v3.0) + /// + /// the + /// The Open Api element. + /// The output stream. + public static void SerializeAsJson(this T element, Stream stream) + where T : IOpenApiElement + { + element.SerializeAsJson(stream, OpenApiSpecVersion.OpenApi3_0); + } + /// /// Serialize the to the given stream as JSON. /// /// the /// The Open Api element. /// The output stream. - /// The Open Api specification version, default is 3.0. - public static void SerializeAsJson(this T element, Stream stream, - OpenApiSpecVersion specVersion = OpenApiSpecVersion.OpenApi3_0) + /// The Open Api specification version + public static void SerializeAsJson(this T element, Stream stream, OpenApiSpecVersion specVersion) where T : IOpenApiElement { element.Serialize(stream, specVersion, OpenApiFormat.Json); } + /// + /// Serialize the to the given stream as YAML (V3.0) + /// + /// the + /// The Open Api element. + /// The output stream. + public static void SerializeAsYaml(this T element, Stream stream) + where T : IOpenApiElement + { + element.SerializeAsYaml(stream, OpenApiSpecVersion.OpenApi3_0); + } + /// /// Serialize the to the given stream as YAML. /// /// the /// The Open Api element. /// The output stream. - /// The Open Api specification version, default is 3.0. - public static void SerializeAsYaml(this T element, Stream stream, - OpenApiSpecVersion specVersion = OpenApiSpecVersion.OpenApi3_0) + /// The Open Api specification version. + public static void SerializeAsYaml(this T element, Stream stream, OpenApiSpecVersion specVersion) where T : IOpenApiElement { element.Serialize(stream, specVersion, OpenApiFormat.Yaml); diff --git a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs index 998c80296..fb34566d6 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs @@ -110,7 +110,10 @@ public override void WritePropertyName(string name) } else { - Writer.WriteLine(); + if (!IsTopLevelObjectScope()) + { + Writer.WriteLine(); + } WriteIndentation(); } } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs index 36aecd9c2..3f6d1d3d5 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs @@ -28,8 +28,8 @@ public class OpenApiContactTests [Theory] [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json, "{ }")] [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json, "{ }")] - [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml, "")] - [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml, "")] + [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml, " ")] + [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml, " ")] public void SerializeBasicContactWorks(OpenApiSpecVersion version, OpenApiFormat format, string expect) { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs index 9c55103d3..36baa3fc0 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs @@ -21,7 +21,7 @@ public class OpenApiExternalDocsTests #region OpenAPI V3 [Theory] [InlineData(OpenApiFormat.Json, "{ }")] - [InlineData(OpenApiFormat.Yaml, "")] + [InlineData(OpenApiFormat.Yaml, " ")] public void SerializeBasicExternalDocsAsV3Works(OpenApiFormat format, string expect) { // Arrange & Act diff --git a/test/Microsoft.OpenApi.Tests/StringExtensions.cs b/test/Microsoft.OpenApi.Tests/StringExtensions.cs index 36f278f07..cbd4384a6 100644 --- a/test/Microsoft.OpenApi.Tests/StringExtensions.cs +++ b/test/Microsoft.OpenApi.Tests/StringExtensions.cs @@ -11,6 +11,15 @@ public static class StringExtensions { public static string MakeLineBreaksEnvironmentNeutral(this string input) { + if (input.IndexOf("\n") == -1) + { + return input; + } + else + { + input = "\r\n" + input; + } + return input.Replace("\r\n", "\n") .Replace("\r", "\n") .Replace("\n", Environment.NewLine); diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index 8176e4de4..7ad96be1f 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -236,8 +236,6 @@ public void WriteMapAsYamlShouldMatchExpected(IDictionary inputM .ToString() .MakeLineBreaksEnvironmentNeutral(); - expectedYaml = expectedYaml.MakeLineBreaksEnvironmentNeutral(); - // Assert Assert.Equal(expectedYaml, actualYaml); } From 25b2c366791b4c9505600044a5e7675e39e9a340 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 15:23:46 -0700 Subject: [PATCH 07/13] make WriteAsV2(3) as internal function in the DOM --- .../Interfaces/IOpenApiElement.cs | 2 +- src/Microsoft.OpenApi/Models/OpenApiCallback.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiComponents.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiContact.cs | 6 +++--- .../Models/OpenApiDiscriminator.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiDocument.cs | 6 +++--- .../OpenApiElement.cs} | 14 ++++++-------- src/Microsoft.OpenApi/Models/OpenApiExample.cs | 6 +++--- .../Models/OpenApiExternalDocs.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiHeader.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiInfo.cs | 7 +++---- src/Microsoft.OpenApi/Models/OpenApiLicense.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiLink.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiMediaType.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiOperation.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiParameter.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiPathItem.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiPaths.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiReference.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiResponse.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 6 +++--- .../Models/OpenApiSecurityRequirement.cs | 6 +++--- .../Models/OpenApiSecurityScheme.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiServer.cs | 6 +++--- .../Models/OpenApiServerVariable.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiTag.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiXml.cs | 6 +++--- .../OpenApiElementSerializeExtensions.cs | 12 ++++++------ .../Models/OpenApiSerializerTestHelper.cs | 6 +++--- 32 files changed, 100 insertions(+), 103 deletions(-) rename src/Microsoft.OpenApi/{Interfaces/IOpenApiWritable.cs => Models/OpenApiElement.cs} (70%) diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs index 92b8bad3b..3a3a7d195 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi.Interfaces /// /// Represents an Open API element. /// - public interface IOpenApiElement : IOpenApiWritable + public interface IOpenApiElement { } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs index c197b03fc..5fbce549e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Callback Object: A map of possible out-of band callbacks related to the parent operation. /// - public class OpenApiCallback : IOpenApiReference, IOpenApiExtension + public class OpenApiCallback : OpenApiElement, IOpenApiReference, IOpenApiExtension { public Dictionary PathItems { get; set; } = new Dictionary(); @@ -24,7 +24,7 @@ public class OpenApiCallback : IOpenApiReference, IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -49,7 +49,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index 2437d6cab..19668a907 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Components Object. /// - public class OpenApiComponents : IOpenApiExtension + public class OpenApiComponents : OpenApiElement, IOpenApiExtension { public IDictionary Schemas { get; set; } = new Dictionary(); public IDictionary Responses { get; set; } = new Dictionary(); @@ -42,7 +42,7 @@ public bool IsEmpty() /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -65,7 +65,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiContact.cs b/src/Microsoft.OpenApi/Models/OpenApiContact.cs index abd5501e9..8e19784df 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiContact.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiContact.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// Contact Object. /// - public class OpenApiContact : IOpenApiExtension + public class OpenApiContact : OpenApiElement, IOpenApiExtension { /// /// The identifying name of the contact person/organization. @@ -40,7 +40,7 @@ public class OpenApiContact : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { WriteInternal(writer); } @@ -48,7 +48,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { WriteInternal(writer); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs index 9ab8a739d..ba4375147 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs @@ -11,12 +11,12 @@ namespace Microsoft.OpenApi.Models /// /// Discriminator object. /// - public class OpenApiDiscriminator : IOpenApiElement + public class OpenApiDiscriminator : OpenApiElement { /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { // nothing here } @@ -24,7 +24,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index f03c2df9d..02af2974e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -16,7 +16,7 @@ namespace Microsoft.OpenApi.Models /// /// Describes an Open API Document. See: https://swagger.io/specification /// - public class OpenApiDocument : IOpenApiExtension + public class OpenApiDocument : OpenApiElement, IOpenApiExtension { string version; public string Version { get { return version; } @@ -52,7 +52,7 @@ public void CreatePath(string key, Action configure) /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -87,7 +87,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiWritable.cs b/src/Microsoft.OpenApi/Models/OpenApiElement.cs similarity index 70% rename from src/Microsoft.OpenApi/Interfaces/IOpenApiWritable.cs rename to src/Microsoft.OpenApi/Models/OpenApiElement.cs index a696d4fd4..cae1a1a62 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiWritable.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiElement.cs @@ -3,25 +3,23 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; -namespace Microsoft.OpenApi.Interfaces +namespace Microsoft.OpenApi.Models { - /// - /// Represents an Open API element is writable. - /// - public interface IOpenApiWritable + public abstract class OpenApiElement : IOpenApiElement { /// /// Write Open API element to v3.0. /// /// The writer. - void WriteAsV3(IOpenApiWriter writer); + internal abstract void WriteAsV3(IOpenApiWriter writer); /// /// Write Open API element to v2.0. /// /// The writer. - void WriteAsV2(IOpenApiWriter writer); + internal abstract void WriteAsV2(IOpenApiWriter writer); } -} +} \ No newline at end of file diff --git a/src/Microsoft.OpenApi/Models/OpenApiExample.cs b/src/Microsoft.OpenApi/Models/OpenApiExample.cs index c72cb4ff4..6800033ba 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExample.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Example Object. /// - public class OpenApiExample : IOpenApiReference, IOpenApiExtension + public class OpenApiExample : OpenApiElement, IOpenApiReference, IOpenApiExtension { /// /// Short description for the example. @@ -43,7 +43,7 @@ public OpenApiReference Pointer /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -71,7 +71,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs b/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs index cfa4a2236..327656b0b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// ExternalDocs object. /// - public class OpenApiExternalDocs : IOpenApiExtension + public class OpenApiExternalDocs : OpenApiElement, IOpenApiExtension { /// /// REQUIRED.The URL for the target documentation. Value MUST be in the format of a URL. @@ -34,7 +34,7 @@ public class OpenApiExternalDocs : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { WriteInternal(writer); } @@ -42,7 +42,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { WriteInternal(writer); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index f6d7d9ad5..76d284421 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// Header Object. /// The Header Object follows the structure of the Parameter Object /// - public class OpenApiHeader : IOpenApiReference, IOpenApiExtension + public class OpenApiHeader : OpenApiElement, IOpenApiReference, IOpenApiExtension { public OpenApiReference Pointer { get; set; } public string Description { get; set; } @@ -34,7 +34,7 @@ public class OpenApiHeader : IOpenApiReference, IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -68,7 +68,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs index 744eb397c..16777095b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiInfo.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiInfo.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -15,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// Open API Info Object, it provides the metadata about the Open API. /// - public class OpenApiInfo : IOpenApiExtension + public class OpenApiInfo : OpenApiElement, IOpenApiExtension { /// /// REQUIRED. The title of the application. @@ -55,7 +54,7 @@ public class OpenApiInfo : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -91,7 +90,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs index bbeded0d3..58967f31b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLicense.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLicense.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// License Object. /// - public class OpenApiLicense : IOpenApiExtension + public class OpenApiLicense : OpenApiElement, IOpenApiExtension { // /// REQUIRED.The license name used for the API. @@ -34,7 +34,7 @@ public class OpenApiLicense : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { WriteInternal(writer); } @@ -42,7 +42,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { WriteInternal(writer); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiLink.cs b/src/Microsoft.OpenApi/Models/OpenApiLink.cs index 64495eca7..7f7ee103a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLink.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLink.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Link Object. /// - public class OpenApiLink : IOpenApiReference, IOpenApiExtension + public class OpenApiLink : OpenApiElement, IOpenApiReference, IOpenApiExtension { public string Href { get; set; } public string OperationId { get; set; } @@ -29,7 +29,7 @@ public class OpenApiLink : IOpenApiReference, IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -53,7 +53,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index b0bedd4e5..976e535b4 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Media Type Object. /// - public class OpenApiMediaType : IOpenApiExtension + public class OpenApiMediaType : OpenApiElement, IOpenApiExtension { public OpenApiSchema Schema { get; set; } public IDictionary Examples { get; set; } @@ -24,7 +24,7 @@ public class OpenApiMediaType : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -41,7 +41,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs index 1cd6b4a14..de6011d4b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// OAuth Flow Object. /// - public class OpenApiOAuthFlow : IOpenApiExtension + public class OpenApiOAuthFlow : OpenApiElement, IOpenApiExtension { /// /// REQUIRED. The authorization URL to be used for this flow. @@ -44,7 +44,7 @@ public class OpenApiOAuthFlow : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -62,7 +62,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs index a18cbaef5..db784d9ca 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlows.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// OAuth Flows Object. /// - public class OpenApiOAuthFlows : IOpenApiExtension + public class OpenApiOAuthFlows : OpenApiElement, IOpenApiExtension { /// /// Configuration for the OAuth Implicit flow @@ -43,7 +43,7 @@ public class OpenApiOAuthFlows : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -61,7 +61,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index 24df75d63..a20db5110 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -15,7 +15,7 @@ namespace Microsoft.OpenApi.Models /// /// Operation Object. /// - public class OpenApiOperation : IOpenApiExtension + public class OpenApiOperation : OpenApiElement, IOpenApiExtension { public IList Tags { get; set; } = new List(); public string Summary { get; set; } @@ -43,7 +43,7 @@ public void CreateResponse(string key, Action configure) /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -70,7 +70,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index 86e6b023f..5159c61bd 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// Parameter Object. /// - public class OpenApiParameter : IOpenApiReference, IOpenApiExtension + public class OpenApiParameter : OpenApiElement, IOpenApiReference, IOpenApiExtension { public OpenApiReference Pointer { get; set; } public string Name { get; set; } @@ -59,7 +59,7 @@ public bool Required /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -93,7 +93,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs index 34e3bcf3d..0dbc0ac66 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs @@ -15,7 +15,7 @@ namespace Microsoft.OpenApi.Models /// /// Path Item Object: to describe the operations available on a single path. /// - public class OpenApiPathItem : IOpenApiExtension + public class OpenApiPathItem : OpenApiElement, IOpenApiExtension { public string Summary { get; set; } public string Description { get; set; } @@ -48,7 +48,7 @@ public void AddOperation(OperationType operationType, OpenApiOperation operation /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -82,7 +82,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs index b95bb9eaf..daec1d0cc 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// Paths object. /// - public class OpenApiPaths : IDictionary, IOpenApiExtension + public class OpenApiPaths : OpenApiElement, IDictionary, IOpenApiExtension { public OpenApiPathItem this[string key] { get => this.PathItems[key]; set => this.PathItems[key] = value; } @@ -93,7 +93,7 @@ IEnumerator> IEnumerable /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -112,7 +112,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiReference.cs b/src/Microsoft.OpenApi/Models/OpenApiReference.cs index aa178183a..c1fbbba2f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiReference.cs @@ -23,7 +23,7 @@ public enum ReferenceType Tags } - public class OpenApiReference : IOpenApiElement + public class OpenApiReference : OpenApiElement { public ReferenceType ReferenceType { get; set; } public string TypeName { get; set; } @@ -136,7 +136,7 @@ public JsonPointer GetLocalPointer() /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { // nothing here } @@ -144,7 +144,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index d31ce921a..a73f29e4d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// Request Body Object /// - public class OpenApiRequestBody : IOpenApiReference, IOpenApiExtension + public class OpenApiRequestBody : OpenApiElement, IOpenApiReference, IOpenApiExtension { public OpenApiReference Pointer { get; set; } @@ -26,7 +26,7 @@ public class OpenApiRequestBody : IOpenApiReference, IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -52,7 +52,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 1eb9132a7..4ea07f12e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -15,7 +15,7 @@ namespace Microsoft.OpenApi.Models /// /// Response object. /// - public class OpenApiResponse : IOpenApiReference, IOpenApiExtension + public class OpenApiResponse : OpenApiElement, IOpenApiReference, IOpenApiExtension { public string Description { get; set; } public IDictionary Content { get; set; } @@ -42,7 +42,7 @@ public void CreateContent(string mediatype, Action configure) /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -71,7 +71,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index df0724f04..84bd370dc 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Schema Object. /// - public class OpenApiSchema : IOpenApiReference, IOpenApiExtension + public class OpenApiSchema : OpenApiElement, IOpenApiReference, IOpenApiExtension { public string Title { get; set; } public string Type { get; set; } @@ -70,7 +70,7 @@ public OpenApiReference Pointer /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -146,7 +146,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs index f4a327166..742de4ce7 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs @@ -12,14 +12,14 @@ namespace Microsoft.OpenApi.Models /// /// Security Requirement Object /// - public class OpenApiSecurityRequirement : IOpenApiElement + public class OpenApiSecurityRequirement : OpenApiElement, IOpenApiElement { public Dictionary> Schemes { get; set; } = new Dictionary>(); /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -51,7 +51,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index d23efb3c2..e1b9e8f38 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// Security Scheme Object. /// - public class OpenApiSecurityScheme : IOpenApiReference, IOpenApiExtension + public class OpenApiSecurityScheme : OpenApiElement, IOpenApiReference, IOpenApiExtension { /// /// REQUIRED. The type of the security scheme. @@ -69,7 +69,7 @@ public OpenApiReference Pointer /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -104,7 +104,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiServer.cs b/src/Microsoft.OpenApi/Models/OpenApiServer.cs index a372cf221..d08c3497f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiServer.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiServer.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Server Object: an object representing a Server. /// - public class OpenApiServer : IOpenApiExtension + public class OpenApiServer : OpenApiElement, IOpenApiExtension { public string Description { get; set; } public string Url { get; set; } @@ -24,7 +24,7 @@ public class OpenApiServer : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -41,7 +41,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs b/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs index ac4573f87..865027677 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiServerVariable.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Server Variable Object. /// - public class OpenApiServerVariable : IOpenApiExtension + public class OpenApiServerVariable : OpenApiElement, IOpenApiExtension { public string Description { get; set; } public string Default { get; set; } @@ -24,7 +24,7 @@ public class OpenApiServerVariable : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -41,7 +41,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/Models/OpenApiTag.cs b/src/Microsoft.OpenApi/Models/OpenApiTag.cs index 835e7233c..6f5a420c0 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiTag.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiTag.cs @@ -13,7 +13,7 @@ namespace Microsoft.OpenApi.Models /// /// Tag Object. /// - public class OpenApiTag : IOpenApiReference, IOpenApiExtension + public class OpenApiTag : OpenApiElement, IOpenApiReference, IOpenApiExtension { /// /// The name of the tag. @@ -43,7 +43,7 @@ OpenApiReference IOpenApiReference.Pointer /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { if (writer == null) { @@ -59,7 +59,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { if (writer == null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiXml.cs b/src/Microsoft.OpenApi/Models/OpenApiXml.cs index 8df4e1eea..d2b96f71b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiXml.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiXml.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.Models /// /// XML Object. /// - public class OpenApiXml : IOpenApiExtension + public class OpenApiXml : OpenApiElement, IOpenApiExtension { /// /// Replaces the name of the element/attribute used for the described schema property. @@ -51,7 +51,7 @@ public class OpenApiXml : IOpenApiExtension /// /// Serialize to Open Api v3.0 /// - public virtual void WriteAsV3(IOpenApiWriter writer) + internal override void WriteAsV3(IOpenApiWriter writer) { // nothing here } @@ -59,7 +59,7 @@ public virtual void WriteAsV3(IOpenApiWriter writer) /// /// Serialize to Open Api v2.0 /// - public virtual void WriteAsV2(IOpenApiWriter writer) + internal override void WriteAsV2(IOpenApiWriter writer) { // nothing here } diff --git a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs index ecdb951d2..39e0c708d 100644 --- a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs +++ b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs @@ -4,7 +4,7 @@ // ------------------------------------------------------------ using System.IO; -using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi @@ -21,7 +21,7 @@ public static class OpenApiElementSerializeExtensions /// The Open Api element. /// The output stream. public static void SerializeAsJson(this T element, Stream stream) - where T : IOpenApiElement + where T : OpenApiElement { element.SerializeAsJson(stream, OpenApiSpecVersion.OpenApi3_0); } @@ -34,7 +34,7 @@ public static void SerializeAsJson(this T element, Stream stream) /// The output stream. /// The Open Api specification version public static void SerializeAsJson(this T element, Stream stream, OpenApiSpecVersion specVersion) - where T : IOpenApiElement + where T : OpenApiElement { element.Serialize(stream, specVersion, OpenApiFormat.Json); } @@ -46,7 +46,7 @@ public static void SerializeAsJson(this T element, Stream stream, OpenApiSpec /// The Open Api element. /// The output stream. public static void SerializeAsYaml(this T element, Stream stream) - where T : IOpenApiElement + where T : OpenApiElement { element.SerializeAsYaml(stream, OpenApiSpecVersion.OpenApi3_0); } @@ -59,7 +59,7 @@ public static void SerializeAsYaml(this T element, Stream stream) /// The output stream. /// The Open Api specification version. public static void SerializeAsYaml(this T element, Stream stream, OpenApiSpecVersion specVersion) - where T : IOpenApiElement + where T : OpenApiElement { element.Serialize(stream, specVersion, OpenApiFormat.Yaml); } @@ -73,7 +73,7 @@ public static void SerializeAsYaml(this T element, Stream stream, OpenApiSpec /// The Open Api specification version. /// The output format (JSON or YAML). public static void Serialize(this T element, Stream stream, OpenApiSpecVersion specVersion, OpenApiFormat format) - where T : IOpenApiElement + where T : OpenApiElement { if (element == null) { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs index 5345cdbba..cddcf066a 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSerializerTestHelper.cs @@ -12,14 +12,14 @@ public static class OpenApiSerializerTestHelper { public static string SerializeAsJson(this T element, OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0) - where T : IOpenApiElement + where T : OpenApiElement { return element.Serialize(version, OpenApiFormat.Json); } public static string SerializeAsYaml(this T element, OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0) - where T : IOpenApiElement + where T : OpenApiElement { return element.Serialize(version, OpenApiFormat.Yaml); } @@ -27,7 +27,7 @@ public static string SerializeAsYaml(this T element, public static string Serialize(this T element, OpenApiSpecVersion version = OpenApiSpecVersion.OpenApi3_0, OpenApiFormat format = OpenApiFormat.Json) - where T : IOpenApiElement + where T : OpenApiElement { if (element == null) { From c6caee241a7da64eef3bedf93e95abc37b0e121f Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 15:27:01 -0700 Subject: [PATCH 08/13] change the Yaml writer for the empty object write --- src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs | 11 ----------- .../Models/OpenApiContactTests.cs | 4 ++-- .../Models/OpenApiExternalDocsTests.cs | 2 +- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs index fb34566d6..4ef01817b 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs @@ -57,12 +57,6 @@ public override void WriteStartObject() public override void WriteEndObject() { Scope currentScope = EndScope(ScopeType.Object); - - if (currentScope.ObjectCount == 0) - { - Writer.Write(WriterConstants.WhiteSpaceForEmptyObjectArray); - } - DecreaseIndentation(); } @@ -81,11 +75,6 @@ public override void WriteStartArray() public override void WriteEndArray() { Scope current = EndScope(ScopeType.Array); - /* - if (current.ObjectCount == 0) - { - Writer.Write(WriterConstants.WhiteSpaceForEmptyObjectArray); - }*/ DecreaseIndentation(); } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs index 3f6d1d3d5..36aecd9c2 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiContactTests.cs @@ -28,8 +28,8 @@ public class OpenApiContactTests [Theory] [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json, "{ }")] [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json, "{ }")] - [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml, " ")] - [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml, " ")] + [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml, "")] + [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml, "")] public void SerializeBasicContactWorks(OpenApiSpecVersion version, OpenApiFormat format, string expect) { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs index 36baa3fc0..9c55103d3 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiExternalDocsTests.cs @@ -21,7 +21,7 @@ public class OpenApiExternalDocsTests #region OpenAPI V3 [Theory] [InlineData(OpenApiFormat.Json, "{ }")] - [InlineData(OpenApiFormat.Yaml, " ")] + [InlineData(OpenApiFormat.Yaml, "")] public void SerializeBasicExternalDocsAsV3Works(OpenApiFormat format, string expect) { // Arrange & Act From 0cdae13292993907b2de93523530da8f4ba7beeb Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 15:53:01 -0700 Subject: [PATCH 09/13] Change the error messages and move them into project resource --- .../OpenApiElementSerializeExtensions.cs | 6 ++++-- .../Properties/SRResource.Designer.cs | 21 +++++++++++++++++-- .../Properties/SRResource.resx | 6 ++++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs index 39e0c708d..d4f637609 100644 --- a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs +++ b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs @@ -3,8 +3,10 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using System; using System.IO; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi @@ -95,7 +97,7 @@ public static void Serialize(this T element, Stream stream, OpenApiSpecVersio writer = new OpenApiYamlWriter(new StreamWriter(stream)); break; default: - throw new OpenApiException("Not supported Open Api document format!"); + throw new OpenApiException(String.Format(SRResource.OpenApiFormatNotSupported, format)); } switch (specVersion) @@ -109,7 +111,7 @@ public static void Serialize(this T element, Stream stream, OpenApiSpecVersio break; default: - throw new OpenApiException("Unknown Open API specification version."); + throw new OpenApiException(String.Format(SRResource.OpenApiSpecVersionNotSupported, specVersion)); } writer.Flush(); diff --git a/src/Microsoft.OpenApi/Properties/SRResource.Designer.cs b/src/Microsoft.OpenApi/Properties/SRResource.Designer.cs index 505bf040f..439393620 100644 --- a/src/Microsoft.OpenApi/Properties/SRResource.Designer.cs +++ b/src/Microsoft.OpenApi/Properties/SRResource.Designer.cs @@ -39,8 +39,7 @@ internal SRResource() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = - new global::System.Resources.ResourceManager(typeof(SRResource).FullName, typeof(SRResource).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.OpenApi.Properties.SRResource", typeof(SRResource).Assembly); resourceMan = temp; } return resourceMan; @@ -88,6 +87,15 @@ internal static string OpenApiExceptionGeneralError { } } + /// + /// Looks up a localized string similar to The given OpenAPI format '{0}' is not supported.. + /// + internal static string OpenApiFormatNotSupported { + get { + return ResourceManager.GetString("OpenApiFormatNotSupported", resourceCulture); + } + } + /// /// Looks up a localized string similar to The object element name '{0}' is required.. /// @@ -115,6 +123,15 @@ internal static string OpenApiParameterRequiredPropertyMandatory { } } + /// + /// Looks up a localized string similar to The given OpenAPI specification version '{0}' is not supported.. + /// + internal static string OpenApiSpecVersionNotSupported { + get { + return ResourceManager.GetString("OpenApiSpecVersionNotSupported", resourceCulture); + } + } + /// /// Looks up a localized string similar to The type '{0}' is not supported in Open API document.. /// diff --git a/src/Microsoft.OpenApi/Properties/SRResource.resx b/src/Microsoft.OpenApi/Properties/SRResource.resx index c2111e094..3a722b8c6 100644 --- a/src/Microsoft.OpenApi/Properties/SRResource.resx +++ b/src/Microsoft.OpenApi/Properties/SRResource.resx @@ -126,6 +126,9 @@ An error occurred while processing the Open API document. + + The given OpenAPI format '{0}' is not supported. + The object element name '{0}' is required. @@ -135,6 +138,9 @@ If the parameter location is "path", this property is REQUIRED and its value MUST be true + + The given OpenAPI specification version '{0}' is not supported. + The type '{0}' is not supported in Open API document. From 079e24c880e023d0e59d558ee4efe2d364670a4c Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 16:01:51 -0700 Subject: [PATCH 10/13] Add the IOpenApiWriter back to public api because the WriteAsV2(3) as internal --- .../OpenApiElementSerializeExtensions.cs | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs index d4f637609..2319c4bbf 100644 --- a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs +++ b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs @@ -77,11 +77,6 @@ public static void SerializeAsYaml(this T element, Stream stream, OpenApiSpec public static void Serialize(this T element, Stream stream, OpenApiSpecVersion specVersion, OpenApiFormat format) where T : OpenApiElement { - if (element == null) - { - throw Error.ArgumentNull(nameof(element)); - } - if (stream == null) { throw Error.ArgumentNull(nameof(stream)); @@ -100,6 +95,41 @@ public static void Serialize(this T element, Stream stream, OpenApiSpecVersio throw new OpenApiException(String.Format(SRResource.OpenApiFormatNotSupported, format)); } + element.Serialize(writer, specVersion); + } + + /// + /// Serialize the to the given stream as JSON (v3.0) + /// + /// the + /// The Open Api element. + /// The output writer. + public static void Serialize(this T element, IOpenApiWriter writer) + where T : OpenApiElement + { + element.Serialize(writer, OpenApiSpecVersion.OpenApi3_0); + } + + /// + /// Serialize the to the given stream as JSON. + /// + /// the + /// The Open Api element. + /// The output writer. + /// The Open Api specification version + public static void Serialize(this T element, IOpenApiWriter writer, OpenApiSpecVersion specVersion) + where T : OpenApiElement + { + if (element == null) + { + throw Error.ArgumentNull(nameof(element)); + } + + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + switch (specVersion) { case OpenApiSpecVersion.OpenApi3_0: From 06841d9c74ac0279d302182416444be29767f66d Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 16:09:18 -0700 Subject: [PATCH 11/13] change the comments in the serialize public api --- .../OpenApiElementSerializeExtensions.cs | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs index 2319c4bbf..6306cd25c 100644 --- a/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs +++ b/src/Microsoft.OpenApi/OpenApiElementSerializeExtensions.cs @@ -12,15 +12,15 @@ namespace Microsoft.OpenApi { /// - /// Represents the Open Api serializer. + /// Extension methods for serialization. /// public static class OpenApiElementSerializeExtensions { /// - /// Serialize the to the given stream as JSON (v3.0) + /// Serialize the to the Open API document (JSON, v3.0) using the given stream. /// - /// the - /// The Open Api element. + /// the + /// The Open API element. /// The output stream. public static void SerializeAsJson(this T element, Stream stream) where T : OpenApiElement @@ -29,12 +29,12 @@ public static void SerializeAsJson(this T element, Stream stream) } /// - /// Serialize the to the given stream as JSON. + /// Serialize the to the Open API document (JSON) using the given stream and specification version. /// /// the - /// The Open Api element. + /// The Open API element. /// The output stream. - /// The Open Api specification version + /// The Open API specification version. public static void SerializeAsJson(this T element, Stream stream, OpenApiSpecVersion specVersion) where T : OpenApiElement { @@ -42,10 +42,10 @@ public static void SerializeAsJson(this T element, Stream stream, OpenApiSpec } /// - /// Serialize the to the given stream as YAML (V3.0) + /// Serialize the to the Open API document (YAML, v3.0) using the given stream. /// /// the - /// The Open Api element. + /// The Open API element. /// The output stream. public static void SerializeAsYaml(this T element, Stream stream) where T : OpenApiElement @@ -54,12 +54,12 @@ public static void SerializeAsYaml(this T element, Stream stream) } /// - /// Serialize the to the given stream as YAML. + /// Serialize the to the Open API document (YAML) using the given stream and specification version. /// - /// the - /// The Open Api element. + /// the + /// The Open API element. /// The output stream. - /// The Open Api specification version. + /// The Open API specification version. public static void SerializeAsYaml(this T element, Stream stream, OpenApiSpecVersion specVersion) where T : OpenApiElement { @@ -67,12 +67,13 @@ public static void SerializeAsYaml(this T element, Stream stream, OpenApiSpec } /// - /// Serialize the to the given stream. + /// Serialize the to the Open API document using + /// the given stream, specification version and the format. /// - /// the - /// The Open Api element. + /// the + /// The Open API element. /// The given stream. - /// The Open Api specification version. + /// The Open API specification version. /// The output format (JSON or YAML). public static void Serialize(this T element, Stream stream, OpenApiSpecVersion specVersion, OpenApiFormat format) where T : OpenApiElement @@ -99,10 +100,10 @@ public static void Serialize(this T element, Stream stream, OpenApiSpecVersio } /// - /// Serialize the to the given stream as JSON (v3.0) + /// Serialize the to Open API document (v3.0) using the given writer. /// - /// the - /// The Open Api element. + /// the + /// The Open API element. /// The output writer. public static void Serialize(this T element, IOpenApiWriter writer) where T : OpenApiElement @@ -111,12 +112,12 @@ public static void Serialize(this T element, IOpenApiWriter writer) } /// - /// Serialize the to the given stream as JSON. + /// Serialize the to Open API document using the given specification version and writer. /// - /// the - /// The Open Api element. + /// the + /// The Open API element. /// The output writer. - /// The Open Api specification version + /// The Open API specification version. public static void Serialize(this T element, IOpenApiWriter writer, OpenApiSpecVersion specVersion) where T : OpenApiElement { From 2bc14da651256c21fca8cd922683bdebe92882bc Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 16:44:19 -0700 Subject: [PATCH 12/13] resolve the typo and change the StringExtensions.cs --- src/Microsoft.OpenApi/Models/OpenApiPaths.cs | 2 +- test/Microsoft.OpenApi.Tests/StringExtensions.cs | 9 --------- .../Writers/OpenApiYamlWriterTests.cs | 4 +++- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs index daec1d0cc..2511f29eb 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs @@ -110,7 +110,7 @@ internal override void WriteAsV3(IOpenApiWriter writer) } /// - /// Serialize to Open Api v3.0 + /// Serialize to Open Api v2.0 /// internal override void WriteAsV2(IOpenApiWriter writer) { diff --git a/test/Microsoft.OpenApi.Tests/StringExtensions.cs b/test/Microsoft.OpenApi.Tests/StringExtensions.cs index cbd4384a6..36f278f07 100644 --- a/test/Microsoft.OpenApi.Tests/StringExtensions.cs +++ b/test/Microsoft.OpenApi.Tests/StringExtensions.cs @@ -11,15 +11,6 @@ public static class StringExtensions { public static string MakeLineBreaksEnvironmentNeutral(this string input) { - if (input.IndexOf("\n") == -1) - { - return input; - } - else - { - input = "\r\n" + input; - } - return input.Replace("\r\n", "\n") .Replace("\r", "\n") .Replace("\n", Environment.NewLine); diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index 7ad96be1f..9ea214a12 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -232,10 +232,12 @@ public void WriteMapAsYamlShouldMatchExpected(IDictionary inputM writer.WriteEndObject(); - var actualYaml = outputString.GetStringBuilder() + var actualYaml = outputString.GetStringBuilder().Insert(0, "\r\n") .ToString() .MakeLineBreaksEnvironmentNeutral(); + expectedYaml = expectedYaml.MakeLineBreaksEnvironmentNeutral(); + // Assert Assert.Equal(expectedYaml, actualYaml); } From 6e40cc6c2ffc96075fb5941bf00a74740958d16d Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 16:54:24 -0700 Subject: [PATCH 13/13] modify the OpenApiSecurityScheme and OpenApiOAuthFlow --- .../Models/OpenApiConstants.cs | 6 ++++ .../Models/OpenApiOAuthFlow.cs | 11 +------- .../Models/OpenApiSecurityScheme.cs | 28 +++++++++++++------ 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs index 37c67ef1d..467c6f7d4 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -161,6 +161,12 @@ internal static class OpenApiConstants public const string OpenApiDocXml = "xml"; + public const string OpenApiDocFlow = "flow"; + + public const string OpenApiDocApplication = "application"; + + public const string OpenApiDocAccessCode = "accessCode"; + public const string OpenApiDocImplicit = "implicit"; public const string OpenApiDocPassword = "password"; diff --git a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs index de6011d4b..73c4ba379 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOAuthFlow.cs @@ -64,16 +64,7 @@ internal override void WriteAsV3(IOpenApiWriter writer) /// internal override void WriteAsV2(IOpenApiWriter writer) { - if (writer == null) - { - throw Error.ArgumentNull(nameof(writer)); - } - - writer.WriteStartObject(); - writer.WriteStringProperty("authorizationUrl", AuthorizationUrl?.ToString()); - writer.WriteStringProperty("tokenUrl", TokenUrl?.ToString()); - writer.WriteMap("scopes", Scopes, (w, s) => w.WriteValue(s)); - writer.WriteEndObject(); + // nothing here } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index e1b9e8f38..b6a0260e6 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -131,7 +131,6 @@ internal override void WriteAsV2(IOpenApiWriter writer) case SecuritySchemeTypeKind.apiKey: writer.WriteStringProperty("in", In.ToString()); writer.WriteStringProperty("name", Name); - break; } @@ -139,26 +138,37 @@ internal override void WriteAsV2(IOpenApiWriter writer) { if (Flows.Implicit != null) { - writer.WriteStringProperty("flow", "implicit"); - Flows.Implicit.WriteAsV2(writer); + WriteOAuthFlowForV2(writer, OpenApiConstants.OpenApiDocImplicit, Flows.AuthorizationCode); } else if (Flows.Password != null) { - writer.WriteStringProperty("flow", "password"); - Flows.Password.WriteAsV2(writer); + WriteOAuthFlowForV2(writer, OpenApiConstants.OpenApiDocPassword, Flows.AuthorizationCode); } else if (Flows.ClientCredentials != null) { - writer.WriteStringProperty("flow", "application"); - Flows.ClientCredentials.WriteAsV2(writer); + WriteOAuthFlowForV2(writer, OpenApiConstants.OpenApiDocApplication, Flows.AuthorizationCode); } else if (Flows.AuthorizationCode != null) { - writer.WriteStringProperty("flow", "accessCode"); - Flows.AuthorizationCode.WriteAsV2(writer); + WriteOAuthFlowForV2(writer, OpenApiConstants.OpenApiDocAccessCode, Flows.AuthorizationCode); } } writer.WriteEndObject(); } + + private static void WriteOAuthFlowForV2(IOpenApiWriter writer, string flowValue, OpenApiOAuthFlow flow) + { + // flow + writer.WriteStringProperty(OpenApiConstants.OpenApiDocFlow, flowValue); + + // authorizationUrl + writer.WriteStringProperty(OpenApiConstants.OpenApiDocAuthorizationUrl, flow.AuthorizationUrl?.ToString()); + + // tokenUrl + writer.WriteStringProperty(OpenApiConstants.OpenApiDocTokenUrl, flow.TokenUrl?.ToString()); + + // scopes + writer.WriteMap(OpenApiConstants.OpenApiDocScopes, flow.Scopes, (w, s) => w.WriteValue(s)); + } } }