From a202ff04a65c2514f8fdc4698e5264ec55c3f22f Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 30 Oct 2017 21:46:36 -0700 Subject: [PATCH 1/3] Modify, clean, refactor for the OpenApiDocument and OpenApiPaths --- .../YamlReaders/OpenApiV3Deserializer.cs | 2 +- .../Models/OpenApiConstants.cs | 11 ++ .../Models/OpenApiDictionaryElement.cs | 90 +++++++++++ .../Models/OpenApiDocument.cs | 150 +++++++++++------- src/Microsoft.OpenApi/Models/OpenApiPaths.cs | 112 +++---------- .../BasicTests.cs | 15 +- .../InfoTests.cs | 2 +- .../Microsoft.OpenApi.Tests.csproj | 1 + .../OpenApiDocumentTestHelper.cs | 20 +++ 9 files changed, 245 insertions(+), 158 deletions(-) create mode 100644 src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs create mode 100644 test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs index 8bc58771e..eca5f2fe4 100644 --- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs +++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs @@ -16,7 +16,7 @@ internal static class OpenApiV3Deserializer { #region OpenApiObject public static FixedFieldMap OpenApiFixedFields = new FixedFieldMap { - { "openapi", (o,n) => { o.Version = n.GetScalarValue(); } }, + { "openapi", (o,n) => { o.Version = new Version(n.GetScalarValue()); } }, { "info", (o,n) => o.Info = LoadInfo(n) }, { "servers", (o,n) => o.Servers = n.CreateList(LoadServer) }, { "paths", (o,n) => o.Paths = LoadPaths(n) }, diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs index 467c6f7d4..c4865d18d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -212,5 +212,16 @@ internal static class OpenApiConstants public static Uri OpenApiDocDefaultUrl = new Uri("http://localhost/"); public const string OpenApiDocDefaultDescription = "Default Description"; + + #region V2 + public const string OpenApiDocHost = "host"; + + public const string OpenApiDocSwagger = "swagger"; + + public const string OpenApiDocBasePath = "basePath"; + + public const string OpenApiDocSchemes = "schemes"; + + #endregion } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs b/src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs new file mode 100644 index 000000000..4a49a18c3 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs @@ -0,0 +1,90 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.Collections; +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models +{ + /// + /// Generic dictionary type for Open API dictionary element. + /// + /// The Open API element, + public abstract class OpenApiDictionaryElement : OpenApiElement, IDictionary + where T : IOpenApiElement + { + public IDictionary Items { get; set; } = new Dictionary(); + + public T this[string key] + { + get => this.Items[key]; + set => this.Items[key] = value; + } + + public ICollection Keys => this.Items.Keys; + + public ICollection Values => this.Items.Values; + + public int Count => this.Items.Count; + + public bool IsReadOnly => this.Items.IsReadOnly; + + public void Add(string key, T value) + { + Items.Add(key, value); + } + + public void Add(KeyValuePair item) + { + Items.Add(item); + } + + public void Clear() + { + this.Items.Clear(); + } + + public bool Contains(KeyValuePair item) + { + return this.Items.Contains(item); + } + + public bool ContainsKey(string key) + { + return this.Items.ContainsKey(key); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + this.Items.CopyTo(array, arrayIndex); + } + + public bool Remove(string key) + { + return this.Items.Remove(key); + } + + public bool Remove(KeyValuePair item) + { + return this.Items.Remove(item); + } + + public bool TryGetValue(string key, out T value) + { + return this.Items.TryGetValue(key, out value); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.Items.GetEnumerator(); + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + return this.Items.GetEnumerator(); + } + } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 02af2974e..75a8da3a6 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -4,9 +4,8 @@ // ------------------------------------------------------------ using System; -using System.Linq; using System.Collections.Generic; -using System.Text.RegularExpressions; +using System.Linq; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -18,39 +17,53 @@ namespace Microsoft.OpenApi.Models /// public class OpenApiDocument : OpenApiElement, IOpenApiExtension { - string version; - public string Version { get { return version; } - set { - if (versionRegex.IsMatch(value)) - { - version = value; - } else - { - throw new OpenApiException("`openapi` property does not match the required format major.minor.patch"); - } - } } // Swagger - + /// + /// REQUIRED.This string MUST be the semantic version number of the OpenAPI Specification version that the OpenAPI document uses. + /// + public Version Version { get; set; } = OpenApiConstants.OpenApiDocDefaultVersion; + /// + /// REQUIRED. Provides metadata about the API. The metadata MAY be used by tooling as required. + /// public OpenApiInfo Info { get; set; } = new OpenApiInfo(); + + /// + /// An array of Server Objects, which provide connectivity information to a target server. + /// public IList Servers { get; set; } = new List(); - public IList SecurityRequirements { get; set; } + + /// + /// REQUIRED. The available paths and operations for the API. + /// public OpenApiPaths Paths { get; set; } = new OpenApiPaths(); + + /// + /// An element to hold various schemas for the specification. + /// public OpenApiComponents Components { get; set; } = new OpenApiComponents(); + + /// + /// A declaration of which security mechanisms can be used across the API. + /// + public IList SecurityRequirements { get; set; } + + /// + /// A list of tags used by the specification with additional metadata. + /// public IList Tags { get; set; } = new List(); - public OpenApiExternalDocs ExternalDocs { get; set; } = new OpenApiExternalDocs(); - public IDictionary Extensions { get; set; } - private static Regex versionRegex = new Regex(@"\d+\.\d+\.\d+"); + /// + /// Additional external documentation. + /// + public OpenApiExternalDocs ExternalDocs { get; set; } = new OpenApiExternalDocs(); - public void CreatePath(string key, Action configure) - { - var pathItem = new OpenApiPathItem(); - configure(pathItem); - Paths.Add(key, pathItem); - } + /// + /// This object MAY be extended with Specification Extensions. + /// + public IDictionary Extensions { get; set; } /// - /// Serialize to Open Api v3.0 + /// Serialize to Open Api v3.0. /// internal override void WriteAsV3(IOpenApiWriter writer) { @@ -60,32 +73,45 @@ internal override void WriteAsV3(IOpenApiWriter 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"); + // openapi + writer.WriteStringProperty(OpenApiConstants.OpenApiDocOpenApi, "3.0.0"); - writer.WriteStartObject(); - Paths.WriteAsV3(writer); - writer.WriteEndObject(); + // info + writer.WriteObject(OpenApiConstants.OpenApiDocInfo, Info, (w, i) => i.WriteAsV3(w)); + + // servers + writer.WriteList(OpenApiConstants.OpenApiDocServers, Servers, (w, s) => s.WriteAsV3(w)); + + // paths + writer.WriteObject(OpenApiConstants.OpenApiDocPaths, Paths, (w, p) => p.WriteAsV3(w)); - writer.WriteList("tags", Tags, (w, t) => t.WriteAsV3(w)); + // components if (!Components.IsEmpty()) { - writer.WriteObject("components", Components, (w, c) => c.WriteAsV3(w)); + writer.WriteObject(OpenApiConstants.OpenApiDocComponents, Components, (w, c) => c.WriteAsV3(w)); } + + // security + writer.WriteList(OpenApiConstants.OpenApiDocSecurity, SecurityRequirements, (w, s) => s.WriteAsV3(w)); + + // tags + writer.WriteList(OpenApiConstants.OpenApiDocTags, Tags, (w, t) => t.WriteAsV3(w)); + + // external docs if (ExternalDocs.Url != null) { - writer.WriteObject("externalDocs", ExternalDocs, (w, e) => e.WriteAsV3(w)); + writer.WriteObject(OpenApiConstants.OpenApiDocExternalDocs, ExternalDocs, (w, e) => e.WriteAsV3(w)); } - writer.WriteList("security", SecurityRequirements, (w, s) => s.WriteAsV3(w)); + + // extensions + writer.WriteExtensions(Extensions); + writer.WriteEndObject(); } /// - /// Serialize to Open Api v2.0 + /// Serialize to Open Api v2.0. /// internal override void WriteAsV2(IOpenApiWriter writer) { @@ -95,34 +121,45 @@ internal override void WriteAsV2(IOpenApiWriter writer) } writer.WriteStartObject(); - writer.WritePropertyName("swagger"); - writer.WriteValue("2.0"); + // swagger + writer.WriteStringProperty(OpenApiConstants.OpenApiDocSwagger, "2.0"); + + // info writer.WriteObject("info", Info, (w, i) => i.WriteAsV2(w)); + + // host, basePath, schemes, consumes, produces SerializeHostInfo(writer, Servers); - writer.WritePropertyName("paths"); + // paths + writer.WriteObject(OpenApiConstants.OpenApiDocPaths, Paths, (w, p) => p.WriteAsV2(w)); - writer.WriteStartObject(); - Paths.WriteAsV2(writer); - writer.WriteEndObject(); + // definitions + // parameters + // responses + // securityDefinitions - writer.WriteList("tags", Tags, (w, t) => t.WriteAsV2(w)); - if (!Components.IsEmpty()) - { - Components.WriteAsV2(writer); - } + // security + writer.WriteList(OpenApiConstants.OpenApiDocSecurity, SecurityRequirements, (w, s) => s.WriteAsV2(w)); + + // tags + writer.WriteList(OpenApiConstants.OpenApiDocTags, Tags, (w, t) => t.WriteAsV2(w)); + + // externalDocs if (ExternalDocs.Url != null) { - writer.WriteObject("externalDocs", ExternalDocs, (w, e) => e.WriteAsV2(w)); + writer.WriteObject(OpenApiConstants.OpenApiDocExternalDocs, ExternalDocs, (w, e) => e.WriteAsV2(w)); } - writer.WriteList("security", SecurityRequirements, (w, s) => s.WriteAsV2(w)); + + // extensions + writer.WriteExtensions(Extensions); + writer.WriteEndObject(); } private static void SerializeHostInfo(IOpenApiWriter writer, IList servers) { - if (servers == null || servers.Count == 0) + if (servers == null || !servers.Any()) { return; } @@ -131,13 +168,16 @@ private static void SerializeHostInfo(IOpenApiWriter writer, IList new Uri(s.Url).Scheme).Distinct(); - writer.WritePropertyName("schemes"); + writer.WritePropertyName(OpenApiConstants.OpenApiDocSchemes); writer.WriteStartArray(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs index 2511f29eb..096d75f1e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs @@ -3,7 +3,7 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -using System.Collections; +using System; using System.Collections.Generic; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; @@ -14,118 +14,48 @@ namespace Microsoft.OpenApi.Models /// /// Paths object. /// - public class OpenApiPaths : OpenApiElement, IDictionary, IOpenApiExtension + public class OpenApiPaths : OpenApiDictionaryElement, IOpenApiExtension { - public OpenApiPathItem this[string key] { get => this.PathItems[key]; set => this.PathItems[key] = value; } - - private IDictionary PathItems { get; set; } = new Dictionary(); + /// + /// This object MAY be extended with Specification Extensions. + /// public IDictionary Extensions { get; set; } - public ICollection Keys => this.PathItems.Keys; - - public ICollection Values => this.PathItems.Values; - - public int Count => this.PathItems.Count; - - public bool IsReadOnly => this.PathItems.IsReadOnly; - - public void Add(string key, OpenApiPathItem value) - { - PathItems.Add(key, value); - } - - public void Add(KeyValuePair item) - { - PathItems.Add(item); - } - - public void Clear() - { - this.PathItems.Clear(); - } - - public bool Contains(KeyValuePair item) - { - return this.PathItems.Contains(item); - } - - public bool ContainsKey(string key) - { - return this.PathItems.ContainsKey(key); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - this.PathItems.CopyTo(array, arrayIndex); - } - - - public bool Remove(string key) - { - return this.PathItems.Remove(key); - } - - public bool Remove(KeyValuePair item) - { - return this.PathItems.Remove(item); - } - - public bool TryGetValue(string key, out OpenApiPathItem value) - { - return this.PathItems.TryGetValue(key, out value); - } - - internal void Validate(List errors) - { - //TODO: - } - - IEnumerator IEnumerable.GetEnumerator() - { - return this.PathItems.GetEnumerator(); - } - - IEnumerator> IEnumerable>.GetEnumerator() - { - return this.PathItems.GetEnumerator(); - } - /// /// Serialize to Open Api v3.0 /// internal override 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(); + WriteInternal(writer, (w, p) => p.WriteAsV3(w)); } /// /// Serialize to Open Api v2.0 /// internal override void WriteAsV2(IOpenApiWriter writer) + { + WriteInternal(writer, (w, p) => p.WriteAsV2(w)); + } + + private void WriteInternal(IOpenApiWriter writer, Action action) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } - //writer.WriteStartObject(); - foreach (var pathItem in this) + writer.WriteStartObject(); + + // path items + foreach (var item in this) { - writer.WritePropertyName(pathItem.Key); - pathItem.Value.WriteAsV2(writer); + writer.WriteObject(item.Key, item.Value, action); } - //writer.WriteEndObject(); + + // extensions + writer.WriteExtensions(Extensions); + + writer.WriteEndObject(); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs b/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs index 682b5e25f..60db6846e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs @@ -20,7 +20,7 @@ public void CheckOpenAPIVersion() var stream = GetType().Assembly.GetManifestResourceStream(typeof(BasicTests), "Samples.petstore30.yaml"); var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); - Assert.Equal("3.0.0", openApiDoc.Version); + Assert.Equal("3.0.0", openApiDoc.Version.ToString()); } [Fact] @@ -41,7 +41,7 @@ public void InlineExample() ", out var parsingContext); - Assert.Equal("3.0.0", openApiDoc.Version); + Assert.Equal("3.0.0", openApiDoc.Version.ToString()); } [Fact] @@ -52,13 +52,8 @@ public void ParseBrokenSimplest() var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); - Assert.Equal(2, context.Errors.Count); - Assert.NotNull( - context.Errors.Where( - s => s.ToString() == - "`openapi` property does not match the required format major.minor.patch at #/openapi") - .FirstOrDefault()); - Assert.NotNull( + Assert.Equal(1, context.Errors.Count); + Assert.NotNull( context.Errors.Where(s => s.ToString() == "title is a required property of #/info").FirstOrDefault()); } @@ -69,7 +64,7 @@ public void ParseSimplestOpenApiEver() var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); - Assert.Equal("1.0.0", openApiDoc.Version); + Assert.Equal("1.0.0", openApiDoc.Version.ToString()); Assert.Empty(openApiDoc.Paths); Assert.Equal("The Api", openApiDoc.Info.Title); Assert.Equal("0.9.1", openApiDoc.Info.Version.ToString()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs index 259c116b8..1e83e97e7 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs @@ -32,7 +32,7 @@ public void ParseCompleteHeaderOpenApi() var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); - Assert.Equal("1.0.0", openApiDoc.Version); + Assert.Equal("1.0.0", openApiDoc.Version.ToString()); Assert.Empty(openApiDoc.Paths); Assert.Equal("The Api", openApiDoc.Info.Title); diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 4d46882b3..e5c3e93c1 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -44,6 +44,7 @@ + diff --git a/test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs b/test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs new file mode 100644 index 000000000..e2bde1ecb --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs @@ -0,0 +1,20 @@ +// ------------------------------------------------------------ +// 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 +{ + internal static class OpenApiDocumentTestHelper + { + public static void CreatePath(this OpenApiDocument doc, string key, Action configure) + { + var pathItem = new OpenApiPathItem(); + configure(pathItem); + doc.Paths.Add(key, pathItem); + } + } +} From 62bafd9caaed382532aca910bdfb1caf7e5e59af Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Tue, 31 Oct 2017 13:38:04 -0700 Subject: [PATCH 2/3] resolve the comments for the OpenApiDocument related --- .../YamlReaders/OpenApiV3Deserializer.cs | 2 +- .../Models/OpenApiConstants.cs | 2 + .../Models/OpenApiDictionaryElement.cs | 69 ++++++++++++++++++- .../Models/OpenApiDocument.cs | 8 +-- src/Microsoft.OpenApi/Models/OpenApiPaths.cs | 26 ++++--- .../BasicTests.cs | 6 +- .../InfoTests.cs | 2 +- .../OpenApiDocumentTestHelper.cs | 4 +- 8 files changed, 97 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs index eca5f2fe4..86ee0b2af 100644 --- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs +++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs @@ -16,7 +16,7 @@ internal static class OpenApiV3Deserializer { #region OpenApiObject public static FixedFieldMap OpenApiFixedFields = new FixedFieldMap { - { "openapi", (o,n) => { o.Version = new Version(n.GetScalarValue()); } }, + { "openapi", (o,n) => { o.SpecVersion = new Version(n.GetScalarValue()); } }, { "info", (o,n) => o.Info = LoadInfo(n) }, { "servers", (o,n) => o.Servers = n.CreateList(LoadServer) }, { "paths", (o,n) => o.Paths = LoadPaths(n) }, diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs index c4865d18d..8c2093295 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -218,6 +218,8 @@ internal static class OpenApiConstants public const string OpenApiDocSwagger = "swagger"; + public const string OpenApiDocSwaggerVersion = "2.0.0"; + public const string OpenApiDocBasePath = "basePath"; public const string OpenApiDocSchemes = "schemes"; diff --git a/src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs b/src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs index 4a49a18c3..03c8ed2b2 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDictionaryElement.cs @@ -16,72 +16,139 @@ namespace Microsoft.OpenApi.Models public abstract class OpenApiDictionaryElement : OpenApiElement, IDictionary where T : IOpenApiElement { - public IDictionary Items { get; set; } = new Dictionary(); + protected IDictionary Items { get; set; } = new Dictionary(); + /// + /// Gets or sets the element with the specified string key. + /// + /// the specified string key. + /// public T this[string key] { get => this.Items[key]; set => this.Items[key] = value; } + /// + /// Gets a collection of the keys. + /// public ICollection Keys => this.Items.Keys; + /// + /// Gets a collection of the values. + /// public ICollection Values => this.Items.Values; + /// + /// Gets the number of elements contained. + /// public int Count => this.Items.Count; + /// + /// Gets a value indicating whether the collection is read-only or not. + /// public bool IsReadOnly => this.Items.IsReadOnly; + /// + /// Adds an item into dictionary. + /// + /// The specified string key. + /// The specified value. public void Add(string key, T value) { Items.Add(key, value); } + /// + /// Adds an item into dictionary. + /// + /// The specified key/value. public void Add(KeyValuePair item) { Items.Add(item); } + /// + /// Clear the dictionary. + /// public void Clear() { this.Items.Clear(); } + /// + /// Determines whether the dictionary contains a specific key/value. + /// + /// The specified key/value. + /// public bool Contains(KeyValuePair item) { return this.Items.Contains(item); } + /// + /// Determines whether the dictionary contains a specific key. + /// + /// The specified key. + /// public bool ContainsKey(string key) { return this.Items.ContainsKey(key); } + /// + /// Copies the elementsto an starting at a particular index. + /// + /// The one-dimensional array that is the destination of the elements copied to. + /// The zero-based index in array at which copying begins. public void CopyTo(KeyValuePair[] array, int arrayIndex) { this.Items.CopyTo(array, arrayIndex); } + /// + /// Removes the first occurrence of a specific object from the collection. + /// + /// The specified key. + /// public bool Remove(string key) { return this.Items.Remove(key); } + /// + /// Removes the first occurrence of a specific object from the collection. + /// + /// The specified key/value. public bool Remove(KeyValuePair item) { return this.Items.Remove(item); } + /// + /// Gets the value associated with the specified key. + /// + /// The specified key. + /// The output value. + /// true if contains an element with the specified key; otherwise, false. public bool TryGetValue(string key, out T value) { return this.Items.TryGetValue(key, out value); } + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator that can be used to iterate through the collection. IEnumerator IEnumerable.GetEnumerator() { return this.Items.GetEnumerator(); } + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator that can be used to iterate through the collection. IEnumerator> IEnumerable>.GetEnumerator() { return this.Items.GetEnumerator(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 75a8da3a6..84c6ac55e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -20,7 +20,7 @@ public class OpenApiDocument : OpenApiElement, IOpenApiExtension /// /// REQUIRED.This string MUST be the semantic version number of the OpenAPI Specification version that the OpenAPI document uses. /// - public Version Version { get; set; } = OpenApiConstants.OpenApiDocDefaultVersion; + public Version SpecVersion { get; set; } = OpenApiConstants.OpenApiDocDefaultVersion; /// /// REQUIRED. Provides metadata about the API. The metadata MAY be used by tooling as required. @@ -75,7 +75,7 @@ internal override void WriteAsV3(IOpenApiWriter writer) writer.WriteStartObject(); // openapi - writer.WriteStringProperty(OpenApiConstants.OpenApiDocOpenApi, "3.0.0"); + writer.WriteStringProperty(OpenApiConstants.OpenApiDocOpenApi, SpecVersion.ToString()); // info writer.WriteObject(OpenApiConstants.OpenApiDocInfo, Info, (w, i) => i.WriteAsV3(w)); @@ -123,10 +123,10 @@ internal override void WriteAsV2(IOpenApiWriter writer) writer.WriteStartObject(); // swagger - writer.WriteStringProperty(OpenApiConstants.OpenApiDocSwagger, "2.0"); + writer.WriteStringProperty(OpenApiConstants.OpenApiDocSwagger, OpenApiConstants.OpenApiDocSwaggerVersion); // info - writer.WriteObject("info", Info, (w, i) => i.WriteAsV2(w)); + writer.WriteObject(OpenApiConstants.OpenApiDocInfo, Info, (w, i) => i.WriteAsV2(w)); // host, basePath, schemes, consumes, produces SerializeHostInfo(writer, Servers); diff --git a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs index 096d75f1e..cf12b7283 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPaths.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPaths.cs @@ -3,7 +3,6 @@ // 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 Microsoft.OpenApi.Interfaces; @@ -26,18 +25,27 @@ public class OpenApiPaths : OpenApiDictionaryElement, IOpenApiE /// internal override void WriteAsV3(IOpenApiWriter writer) { - WriteInternal(writer, (w, p) => p.WriteAsV3(w)); + if (writer == null) + { + throw Error.ArgumentNull(nameof(writer)); + } + + writer.WriteStartObject(); + + foreach (var item in this) + { + writer.WriteObject(item.Key, item.Value, (w, p) => p.WriteAsV3(w)); + } + + writer.WriteExtensions(Extensions); + + writer.WriteEndObject(); } /// /// Serialize to Open Api v2.0 /// internal override void WriteAsV2(IOpenApiWriter writer) - { - WriteInternal(writer, (w, p) => p.WriteAsV2(w)); - } - - private void WriteInternal(IOpenApiWriter writer, Action action) { if (writer == null) { @@ -46,13 +54,11 @@ private void WriteInternal(IOpenApiWriter writer, Action p.WriteAsV2(w)); } - // extensions writer.WriteExtensions(Extensions); writer.WriteEndObject(); diff --git a/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs b/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs index 60db6846e..4406aa565 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs @@ -20,7 +20,7 @@ public void CheckOpenAPIVersion() var stream = GetType().Assembly.GetManifestResourceStream(typeof(BasicTests), "Samples.petstore30.yaml"); var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); - Assert.Equal("3.0.0", openApiDoc.Version.ToString()); + Assert.Equal("3.0.0", openApiDoc.SpecVersion.ToString()); } [Fact] @@ -41,7 +41,7 @@ public void InlineExample() ", out var parsingContext); - Assert.Equal("3.0.0", openApiDoc.Version.ToString()); + Assert.Equal("3.0.0", openApiDoc.SpecVersion.ToString()); } [Fact] @@ -64,7 +64,7 @@ public void ParseSimplestOpenApiEver() var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); - Assert.Equal("1.0.0", openApiDoc.Version.ToString()); + Assert.Equal("1.0.0", openApiDoc.SpecVersion.ToString()); Assert.Empty(openApiDoc.Paths); Assert.Equal("The Api", openApiDoc.Info.Title); Assert.Equal("0.9.1", openApiDoc.Info.Version.ToString()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs index 1e83e97e7..f2b5d8c88 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs @@ -32,7 +32,7 @@ public void ParseCompleteHeaderOpenApi() var openApiDoc = new OpenApiStreamReader().Read(stream, out var context); - Assert.Equal("1.0.0", openApiDoc.Version.ToString()); + Assert.Equal("1.0.0", openApiDoc.SpecVersion.ToString()); Assert.Empty(openApiDoc.Paths); Assert.Equal("The Api", openApiDoc.Info.Title); diff --git a/test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs b/test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs index e2bde1ecb..2c9aecc33 100644 --- a/test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs +++ b/test/Microsoft.OpenApi.Tests/OpenApiDocumentTestHelper.cs @@ -10,11 +10,11 @@ namespace Microsoft.OpenApi.Tests { internal static class OpenApiDocumentTestHelper { - public static void CreatePath(this OpenApiDocument doc, string key, Action configure) + public static void CreatePath(this OpenApiDocument document, string key, Action configure) { var pathItem = new OpenApiPathItem(); configure(pathItem); - doc.Paths.Add(key, pathItem); + document.Paths.Add(key, pathItem); } } } From dd2a9db6ebffc933d6482810f2b370980edb905d Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Tue, 31 Oct 2017 15:05:48 -0700 Subject: [PATCH 3/3] change SerializeHostInfo to WriteHostInfo --- src/Microsoft.OpenApi/Models/OpenApiDocument.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 84c6ac55e..16a79d813 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -129,7 +129,7 @@ internal override void WriteAsV2(IOpenApiWriter writer) writer.WriteObject(OpenApiConstants.OpenApiDocInfo, Info, (w, i) => i.WriteAsV2(w)); // host, basePath, schemes, consumes, produces - SerializeHostInfo(writer, Servers); + WriteHostInfo(writer, Servers); // paths writer.WriteObject(OpenApiConstants.OpenApiDocPaths, Paths, (w, p) => p.WriteAsV2(w)); @@ -157,7 +157,7 @@ internal override void WriteAsV2(IOpenApiWriter writer) writer.WriteEndObject(); } - private static void SerializeHostInfo(IOpenApiWriter writer, IList servers) + private static void WriteHostInfo(IOpenApiWriter writer, IList servers) { if (servers == null || !servers.Any()) {