From aebefb76094e71718b1d60691e9ac12a95a25283 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 28 Jan 2025 16:52:02 -0500 Subject: [PATCH 1/4] fix: open api schema reference proxy design pattern implementation Signed-off-by: Vincent Biret --- .../Formatters/PowerShellFormatter.cs | 46 +- src/Microsoft.OpenApi.Hidi/StatsVisitor.cs | 2 +- .../StatsVisitor.cs | 2 +- .../Models/Interfaces/IOpenApiHeader.cs | 2 +- .../Models/Interfaces/IOpenApiParameter.cs | 2 +- .../Models/Interfaces/IOpenApiSchema.cs | 304 +++++++++++++ .../Models/OpenApiComponents.cs | 6 +- .../Models/OpenApiDocument.cs | 20 +- src/Microsoft.OpenApi/Models/OpenApiHeader.cs | 12 +- .../Models/OpenApiMediaType.cs | 10 +- .../Models/OpenApiParameter.cs | 16 +- .../Models/OpenApiRequestBody.cs | 2 +- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 417 ++++++------------ .../References/BaseOpenApiReferenceHolder.cs | 6 +- .../References/OpenApiHeaderReference.cs | 2 +- .../References/OpenApiParameterReference.cs | 2 +- .../References/OpenApiSchemaReference.cs | 287 ++++-------- .../Reader/ParseNodes/AnyFieldMapParameter.cs | 5 +- .../ParseNodes/AnyMapFieldMapParameter.cs | 5 +- .../Reader/V2/OpenApiHeaderDeserializer.cs | 9 +- .../Reader/V2/OpenApiOperationDeserializer.cs | 21 +- .../Reader/V2/OpenApiParameterDeserializer.cs | 7 +- .../Reader/V2/OpenApiResponseDeserializer.cs | 4 +- .../Reader/V2/OpenApiSchemaDeserializer.cs | 6 +- .../Reader/V3/OpenApiSchemaDeserializer.cs | 6 +- .../Reader/V31/OpenApiSchemaDeserializer.cs | 6 +- .../Services/CopyReferences.cs | 12 +- .../Services/OpenApiVisitorBase.cs | 4 +- .../Services/OpenApiWalker.cs | 12 +- .../Validations/OpenApiValidator.cs | 2 +- .../Rules/OpenApiNonDefaultRules.cs | 4 +- .../Validations/Rules/OpenApiSchemaRules.cs | 12 +- .../Validations/Rules/RuleHelpers.cs | 3 +- .../Formatters/PowerShellFormatterTests.cs | 20 +- .../Services/OpenApiFilterServiceTests.cs | 2 +- .../UtilityFiles/OpenApiDocumentMock.cs | 91 ++-- .../TryLoadReferenceV2Tests.cs | 30 +- .../V2Tests/OpenApiDocumentTests.cs | 21 +- .../V2Tests/OpenApiHeaderTests.cs | 4 +- .../V2Tests/OpenApiOperationTests.cs | 14 +- .../V2Tests/OpenApiParameterTests.cs | 16 +- .../V2Tests/OpenApiPathItemTests.cs | 45 +- .../V2Tests/OpenApiSchemaTests.cs | 5 +- .../V31Tests/OpenApiDocumentTests.cs | 62 +-- .../V31Tests/OpenApiSchemaTests.cs | 37 +- .../V3Tests/OpenApiCallbackTests.cs | 8 +- .../V3Tests/OpenApiDocumentTests.cs | 163 ++++--- .../V3Tests/OpenApiEncodingTests.cs | 2 +- .../V3Tests/OpenApiMediaTypeTests.cs | 4 +- .../V3Tests/OpenApiOperationTests.cs | 4 +- .../V3Tests/OpenApiParameterTests.cs | 32 +- .../V3Tests/OpenApiSchemaTests.cs | 30 +- .../Models/OpenApiCallbackTests.cs | 4 +- .../Models/OpenApiComponentsTests.cs | 54 +-- .../Models/OpenApiDocumentTests.cs | 171 ++++--- .../Models/OpenApiHeaderTests.cs | 4 +- .../Models/OpenApiOperationTests.cs | 26 +- .../Models/OpenApiParameterTests.cs | 50 +-- .../Models/OpenApiRequestBodyTests.cs | 4 +- .../Models/OpenApiResponseTests.cs | 31 +- .../Models/OpenApiSchemaTests.cs | 75 ++-- .../OpenApiRequestBodyReferenceTests.cs | 6 +- .../OpenApiResponseReferenceTest.cs | 6 +- .../PublicApi/PublicApi.approved.txt | 310 +++++++------ .../OpenApiMediaTypeValidationTests.cs | 6 +- .../OpenApiParameterValidationTests.cs | 10 +- .../OpenApiReferenceValidationTests.cs | 25 +- .../OpenApiSchemaValidationTests.cs | 48 +- .../Visitors/InheritanceTests.cs | 4 +- .../Walkers/WalkerLocationTests.cs | 24 +- .../Workspaces/OpenApiWorkspaceTests.cs | 26 +- .../Writers/OpenApiYamlWriterTests.cs | 9 +- 72 files changed, 1365 insertions(+), 1374 deletions(-) create mode 100644 src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index a6b6380d6..2224f6f96 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -16,7 +16,7 @@ internal class PowerShellFormatter : OpenApiVisitorBase { private const string DefaultPutPrefix = ".Update"; private const string PowerShellPutPrefix = ".Set"; - private readonly Stack _schemaLoop = new(); + private readonly Stack _schemaLoop = new(); private static readonly Regex s_oDataCastRegex = new("(.*(?<=[a-z]))\\.(As(?=[A-Z]).*)", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); private static readonly Regex s_hashSuffixRegex = new(@"^[^-]+", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); private static readonly Regex s_oDataRefRegex = new("(?<=[a-z])Ref(?=[A-Z])", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); @@ -42,7 +42,7 @@ static PowerShellFormatter() // 5. Fix anyOf and oneOf schema. // 6. Add AdditionalProperties to object schemas. - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { AddAdditionalPropertiesToSchema(schema); ResolveAnyOfSchema(schema); @@ -165,10 +165,10 @@ private static void ResolveFunctionParameters(IList parameter // Replace content with a schema object of type array // for structured or collection-valued function parameters parameter.Content = null; - parameter.Schema = new() + parameter.Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -176,11 +176,11 @@ private static void ResolveFunctionParameters(IList parameter } } - private void AddAdditionalPropertiesToSchema(OpenApiSchema schema) + private void AddAdditionalPropertiesToSchema(IOpenApiSchema schema) { - if (schema != null && !_schemaLoop.Contains(schema) && schema.Type.Equals(JsonSchemaType.Object)) + if (schema is OpenApiSchema openApiSchema && !_schemaLoop.Contains(schema) && schema.Type.Equals(JsonSchemaType.Object)) { - schema.AdditionalProperties = new() { Type = JsonSchemaType.Object }; + openApiSchema.AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Object }; /* Because 'additionalProperties' are now being walked, * we need a way to keep track of visited schemas to avoid @@ -190,39 +190,29 @@ private void AddAdditionalPropertiesToSchema(OpenApiSchema schema) } } - private static void ResolveOneOfSchema(OpenApiSchema schema) + private static void ResolveOneOfSchema(IOpenApiSchema schema) { - if (schema.OneOf?.FirstOrDefault() is { } newSchema) + if (schema is OpenApiSchema openApiSchema && schema.OneOf?.FirstOrDefault() is OpenApiSchema newSchema) { - schema.OneOf = null; - FlattenSchema(schema, newSchema); + openApiSchema.OneOf = null; + FlattenSchema(openApiSchema, newSchema); } } - private static void ResolveAnyOfSchema(OpenApiSchema schema) + private static void ResolveAnyOfSchema(IOpenApiSchema schema) { - if (schema.AnyOf?.FirstOrDefault() is { } newSchema) + if (schema is OpenApiSchema openApiSchema && schema.AnyOf?.FirstOrDefault() is OpenApiSchema newSchema) { - schema.AnyOf = null; - FlattenSchema(schema, newSchema); + openApiSchema.AnyOf = null; + FlattenSchema(openApiSchema, newSchema); } } private static void FlattenSchema(OpenApiSchema schema, OpenApiSchema newSchema) { - if (newSchema != null) - { - if (newSchema.Reference != null) - { - schema.Reference = newSchema.Reference; - schema.UnresolvedReference = true; - } - else - { - // Copies schema properties based on https://github.com/microsoft/OpenAPI.NET.OData/pull/264. - CopySchema(schema, newSchema); - } - } + if (newSchema is null) return; + // Copies schema properties based on https://github.com/microsoft/OpenAPI.NET.OData/pull/264. + CopySchema(schema, newSchema); } private static void CopySchema(OpenApiSchema schema, OpenApiSchema newSchema) diff --git a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs index 645f94319..d157a6c42 100644 --- a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs @@ -20,7 +20,7 @@ public override void Visit(IOpenApiParameter parameter) public int SchemaCount { get; set; } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { SchemaCount++; } diff --git a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs index fbf9f3c9a..85dc824a4 100644 --- a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs @@ -20,7 +20,7 @@ public override void Visit(IOpenApiParameter parameter) public int SchemaCount { get; set; } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { SchemaCount++; } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs index 9931775c7..9caca85f6 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -45,7 +45,7 @@ public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiSerializable /// /// The schema defining the type used for the request body. /// - public OpenApiSchema Schema { get; } + public IOpenApiSchema Schema { get; } /// /// Example of the media type. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs index 363cc1cd4..ff6c2994f 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs @@ -72,7 +72,7 @@ public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiSerializa /// /// The schema defining the type used for the parameter. /// - public OpenApiSchema Schema { get; } + public IOpenApiSchema Schema { get; } /// /// Examples of the media type. Each example SHOULD contain a value diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs new file mode 100644 index 000000000..5495ab307 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs @@ -0,0 +1,304 @@ +using System.Collections.Generic; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the schema object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiSchema : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +{ + + /// + /// Follow JSON Schema definition. Short text providing information about the data. + /// + public string Title { get; } + + /// + /// $schema, a JSON Schema dialect identifier. Value must be a URI + /// + public string Schema { get; } + + /// + /// $id - Identifies a schema resource with its canonical URI. + /// + public string Id { get; } + + /// + /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. + /// + public string Comment { get; } + + /// + /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. + /// + public IDictionary Vocabulary { get; } + + /// + /// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance + /// + public string DynamicRef { get; } + + /// + /// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. + /// + public string DynamicAnchor { get; } + + /// + /// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. + /// The keyword does not directly affect the validation result + /// + public IDictionary Definitions { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? V31ExclusiveMaximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? V31ExclusiveMinimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool UnEvaluatedProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value MUST be a string in V2 and V3. + /// + public JsonSchemaType? Type { get; } + + /// + /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation + /// + public string Const { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// While relying on JSON Schema's defined formats, + /// the OAS offers a few additional predefined formats. + /// + public string Format { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? Maximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? ExclusiveMaximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? Minimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? ExclusiveMinimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxLength { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinLength { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect + /// + public string Pattern { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? MultipleOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. + /// Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. + /// For example, if type is string, then default can be "foo" but cannot be 1. + /// + public JsonNode Default { get; } + + /// + /// Relevant only for Schema "properties" definitions. Declares the property as "read only". + /// This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. + /// If the property is marked as readOnly being true and is in the required list, + /// the required will take effect on the response only. + /// A property MUST NOT be marked as both readOnly and writeOnly being true. + /// Default value is false. + /// + public bool ReadOnly { get; } + + /// + /// Relevant only for Schema "properties" definitions. Declares the property as "write only". + /// Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. + /// If the property is marked as writeOnly being true and is in the required list, + /// the required will take effect on the request only. + /// A property MUST NOT be marked as both readOnly and writeOnly being true. + /// Default value is false. + /// + public bool WriteOnly { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList AllOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList OneOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList AnyOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IOpenApiSchema Not { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public ISet Required { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object + /// and not a standard JSON Schema. items MUST be present if the type is array. + /// + public IOpenApiSchema Items { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? UniqueItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Property definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced). + /// + public IDictionary Properties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// PatternProperty definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced) + /// Each property name of this object SHOULD be a valid regular expression according to the ECMA 262 r + /// egular expression dialect. Each property value of this object MUST be an object, and each object MUST + /// be a valid Schema Object not a standard JSON Schema. + /// + public IDictionary PatternProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinProperties { get; } + + /// + /// Indicates if the schema can contain properties other than those defined by the properties map. + /// + public bool AdditionalPropertiesAllowed { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value can be boolean or object. Inline or referenced schema + /// MUST be of a Schema Object and not a standard JSON Schema. + /// + public IOpenApiSchema AdditionalProperties { get; } + + /// + /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate + /// between other schemas which may satisfy the payload description. + /// + public OpenApiDiscriminator Discriminator { get; } + + /// + /// A free-form property to include an example of an instance for this schema. + /// To represent examples that cannot be naturally represented in JSON or YAML, + /// a string value can be used to contain the example with escaping where necessary. + /// + public JsonNode Example { get; } + + /// + /// A free-form property to include examples of an instance for this schema. + /// To represent examples that cannot be naturally represented in JSON or YAML, + /// a list of values can be used to contain the examples with escaping where necessary. + /// + public IList Examples { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public IList Enum { get; } + + /// + /// Allows sending a null value for the defined schema. Default value is false. + /// + public bool Nullable { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool UnevaluatedProperties { get; } + + /// + /// Additional external documentation for this schema. + /// + public OpenApiExternalDocs ExternalDocs { get; } + + /// + /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage. + /// Default value is false. + /// + public bool Deprecated { get; } + + /// + /// This MAY be used only on properties schemas. It has no effect on root schemas. + /// Adds additional metadata to describe the XML representation of this property. + /// + public OpenApiXml Xml { get; } + + /// + /// This object stores any unrecognized keywords found in the schema. + /// + public IDictionary UnrecognizedKeywords { get; } + + /// + public IDictionary Annotations { get; } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index 6d65ef7b1..6b735087e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -18,9 +18,9 @@ namespace Microsoft.OpenApi.Models public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible { /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public IDictionary? Schemas { get; set; } = new Dictionary(); + public IDictionary? Schemas { get; set; } = new Dictionary(); /// /// An object to hold reusable Objects. @@ -85,7 +85,7 @@ public OpenApiComponents() { } /// public OpenApiComponents(OpenApiComponents? components) { - Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; + Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; Responses = components?.Responses != null ? new Dictionary(components.Responses) : null; Parameters = components?.Parameters != null ? new Dictionary(components.Parameters) : null; Examples = components?.Examples != null ? new Dictionary(components.Examples) : null; diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 32afbdf90..eaf436793 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -239,10 +239,10 @@ public void SerializeAsV2(IOpenApiWriter writer) { var loops = writer.GetSettings().LoopDetector.Loops; - if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas)) + if (loops.TryGetValue(typeof(IOpenApiSchema), out var schemas)) { - var openApiSchemas = schemas.Cast().Distinct().ToList() - .ToDictionary(k => k.Reference.Id); + var openApiSchemas = schemas.Cast().Distinct().OfType() + .ToDictionary(k => k.Reference.Id, v => v); foreach (var schema in openApiSchemas.Values.ToList()) { @@ -588,7 +588,7 @@ public bool AddComponent(string id, T componentToRegister) switch (componentToRegister) { case OpenApiSchema openApiSchema: - Components.Schemas ??= new Dictionary(); + Components.Schemas ??= new Dictionary(); Components.Schemas.Add(id, openApiSchema); break; case OpenApiParameter openApiParameter: @@ -636,9 +636,9 @@ public bool AddComponent(string id, T componentToRegister) internal class FindSchemaReferences : OpenApiVisitorBase { - private Dictionary Schemas = new(); + private Dictionary Schemas = new(StringComparer.Ordinal); - public static void ResolveSchemas(OpenApiComponents? components, Dictionary schemas) + public static void ResolveSchemas(OpenApiComponents? components, Dictionary schemas) { var visitor = new FindSchemaReferences(); visitor.Schemas = schemas; @@ -651,7 +651,7 @@ public override void Visit(IOpenApiReferenceHolder referenceHolder) { switch (referenceHolder) { - case OpenApiSchema schema: + case OpenApiSchemaReference schema: if (!Schemas.ContainsKey(schema.Reference.Id)) { Schemas.Add(schema.Reference.Id, schema); @@ -664,12 +664,12 @@ public override void Visit(IOpenApiReferenceHolder referenceHolder) base.Visit(referenceHolder); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { // This is needed to handle schemas used in Responses in components - if (schema.Reference != null && !Schemas.ContainsKey(schema.Reference.Id)) + if (schema is OpenApiSchemaReference {Reference: not null} schemaReference && !Schemas.ContainsKey(schemaReference.Reference.Id)) { - Schemas.Add(schema.Reference.Id, schema); + Schemas.Add(schemaReference.Reference.Id, schema); } base.Visit(schema); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index 1f382220b..d1240bbd0 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -40,7 +41,7 @@ public class OpenApiHeader : IOpenApiHeader, IOpenApiReferenceable, IOpenApiExte public bool AllowReserved { get; set; } /// - public OpenApiSchema Schema { get; set; } + public IOpenApiSchema Schema { get; set; } /// public JsonNode Example { get; set; } @@ -71,7 +72,7 @@ public OpenApiHeader(IOpenApiHeader header) Style = header?.Style ?? Style; Explode = header?.Explode ?? Explode; AllowReserved = header?.AllowReserved ?? AllowReserved; - Schema = header?.Schema != null ? new(header.Schema) : null; + Schema = header?.Schema != null ? new OpenApiSchema(header.Schema) : null; Example = header?.Example != null ? JsonNodeCloneHelper.Clone(header.Example) : null; Examples = header?.Examples != null ? new Dictionary(header.Examples) : null; Content = header?.Content != null ? new Dictionary(header.Content) : null; @@ -171,7 +172,12 @@ public void SerializeAsV2(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - Schema.WriteAsItemsProperties(writer); + var targetSchema = Schema switch { + OpenApiSchemaReference schemaReference => schemaReference.Target, + OpenApiSchema schema => schema, + _ => null, + }; + targetSchema?.WriteAsItemsProperties(writer); // example writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, s) => w.WriteAny(s)); diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 23acd0de9..d350c3251 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -19,16 +19,10 @@ namespace Microsoft.OpenApi.Models /// public class OpenApiMediaType : IOpenApiSerializable, IOpenApiExtensible { - private OpenApiSchema? _schema; - /// /// The schema defining the type used for the request body. /// - public virtual OpenApiSchema? Schema - { - get => _schema; - set => _schema = value; - } + public virtual IOpenApiSchema? Schema { get; set; } /// /// Example of the media type. @@ -65,7 +59,7 @@ public OpenApiMediaType() { } /// public OpenApiMediaType(OpenApiMediaType? mediaType) { - _schema = mediaType?.Schema != null ? new(mediaType.Schema) : null; + Schema = mediaType?.Schema != null ? new OpenApiSchema(mediaType.Schema) : null; Example = mediaType?.Example != null ? JsonNodeCloneHelper.Clone(mediaType.Example) : null; Examples = mediaType?.Examples != null ? new Dictionary(mediaType.Examples) : null; Encoding = mediaType?.Encoding != null ? new Dictionary(mediaType.Encoding) : null; diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index 87a761c8b..27c443a5b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -9,6 +9,7 @@ using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -57,7 +58,7 @@ public bool Explode public bool AllowReserved { get; set; } /// - public OpenApiSchema Schema { get; set; } + public IOpenApiSchema Schema { get; set; } /// public IDictionary Examples { get; set; } = new Dictionary(); @@ -89,7 +90,7 @@ public OpenApiParameter(IOpenApiParameter parameter) Style = parameter.Style ?? Style; Explode = parameter.Explode; AllowReserved = parameter.AllowReserved; - Schema = parameter.Schema != null ? new(parameter.Schema) : null; + Schema = parameter.Schema != null ? new OpenApiSchema(parameter.Schema) : null; Examples = parameter.Examples != null ? new Dictionary(parameter.Examples) : null; Example = parameter.Example != null ? JsonNodeCloneHelper.Clone(parameter.Example) : null; Content = parameter.Content != null ? new Dictionary(parameter.Content) : null; @@ -207,7 +208,7 @@ public void SerializeAsV2(IOpenApiWriter writer) } // In V2 parameter's type can't be a reference to a custom object schema or can't be of type object // So in that case map the type as string. - else if (Schema?.UnresolvedReference == true || Schema?.Type == JsonSchemaType.Object) + else if (Schema is OpenApiSchemaReference { UnresolvedReference: true } || (Schema?.Type & JsonSchemaType.Object) == JsonSchemaType.Object) { writer.WriteProperty(OpenApiConstants.Type, "string"); } @@ -230,9 +231,14 @@ public void SerializeAsV2(IOpenApiWriter writer) // uniqueItems // enum // multipleOf - if (Schema != null) + var targetSchema = Schema switch { + OpenApiSchemaReference schemaReference => schemaReference.Target, + OpenApiSchema schema => schema, + _ => null, + }; + if (targetSchema is not null) { - Schema.WriteAsItemsProperties(writer); + targetSchema.WriteAsItemsProperties(writer); var extensions = Schema.Extensions; if (extensions != null) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index b5fd3f605..029a6d407 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -123,7 +123,7 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter foreach (var property in Content.First().Value.Schema.Properties) { - var paramSchema = property.Value; + var paramSchema = new OpenApiSchema(property.Value); if ((paramSchema.Type & JsonSchemaType.String) == JsonSchemaType.String && ("binary".Equals(paramSchema.Format, StringComparison.OrdinalIgnoreCase) || "base64".Equals(paramSchema.Format, StringComparison.OrdinalIgnoreCase))) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index ff5a8eb48..aae5723e8 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -15,316 +16,163 @@ namespace Microsoft.OpenApi.Models /// /// The Schema Object allows the definition of input and output data types. /// - public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiReferenceable, IOpenApiReferenceHolder - {//TODO remove the implementation of IOpenAPiReferenceHolder when we have removed the inheritance from the inheritance type to this type - /// - /// Follow JSON Schema definition. Short text providing information about the data. - /// - public virtual string Title { get; set; } - - /// - /// $schema, a JSON Schema dialect identifier. Value must be a URI - /// - public virtual string Schema { get; set; } - - /// - /// $id - Identifies a schema resource with its canonical URI. - /// - public virtual string Id { get; set; } + public class OpenApiSchema : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiSchema + { + /// + public string Title { get; set; } - /// - /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. - /// - public virtual string Comment { get; set; } + /// + public string Schema { get; set; } - /// - /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. - /// - public virtual IDictionary Vocabulary { get; set; } + /// + public string Id { get; set; } - /// - /// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance - /// - public virtual string DynamicRef { get; set; } + /// + public string Comment { get; set; } - /// - /// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. - /// - public virtual string DynamicAnchor { get; set; } + /// + public IDictionary Vocabulary { get; set; } - /// - /// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. - /// The keyword does not directly affect the validation result - /// - public virtual IDictionary Definitions { get; set; } + /// + public string DynamicRef { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? V31ExclusiveMaximum { get; set; } + /// + public string DynamicAnchor { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? V31ExclusiveMinimum { get; set; } + /// + public IDictionary Definitions { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool UnEvaluatedProperties { get; set; } + /// + public decimal? V31ExclusiveMaximum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value MUST be a string in V2 and V3. - /// - public virtual JsonSchemaType? Type { get; set; } + /// + public decimal? V31ExclusiveMinimum { get; set; } - /// - /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation - /// - public virtual string Const { get; set; } + /// + public bool UnEvaluatedProperties { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// While relying on JSON Schema's defined formats, - /// the OAS offers a few additional predefined formats. - /// - public virtual string Format { get; set; } + /// + public JsonSchemaType? Type { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public string Const { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? Maximum { get; set; } + /// + public string Format { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? ExclusiveMaximum { get; set; } + /// + public string Description { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? Minimum { get; set; } + /// + public decimal? Maximum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? ExclusiveMinimum { get; set; } + /// + public bool? ExclusiveMaximum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxLength { get; set; } + /// + public decimal? Minimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinLength { get; set; } + /// + public bool? ExclusiveMinimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect - /// - public virtual string Pattern { get; set; } + /// + public int? MaxLength { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? MultipleOf { get; set; } + /// + public int? MinLength { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. - /// Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. - /// For example, if type is string, then default can be "foo" but cannot be 1. - /// - public virtual JsonNode Default { get; set; } + /// + public string Pattern { get; set; } - /// - /// Relevant only for Schema "properties" definitions. Declares the property as "read only". - /// This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. - /// If the property is marked as readOnly being true and is in the required list, - /// the required will take effect on the response only. - /// A property MUST NOT be marked as both readOnly and writeOnly being true. - /// Default value is false. - /// - public virtual bool ReadOnly { get; set; } + /// + public decimal? MultipleOf { get; set; } - /// - /// Relevant only for Schema "properties" definitions. Declares the property as "write only". - /// Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. - /// If the property is marked as writeOnly being true and is in the required list, - /// the required will take effect on the request only. - /// A property MUST NOT be marked as both readOnly and writeOnly being true. - /// Default value is false. - /// - public virtual bool WriteOnly { get; set; } + /// + public JsonNode Default { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList AllOf { get; set; } = new List(); + /// + public bool ReadOnly { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList OneOf { get; set; } = new List(); + /// + public bool WriteOnly { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList AnyOf { get; set; } = new List(); + /// + public IList AllOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual OpenApiSchema Not { get; set; } + /// + public IList OneOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual ISet Required { get; set; } = new HashSet(); + /// + public IList AnyOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object - /// and not a standard JSON Schema. items MUST be present if the type is array. - /// - public virtual OpenApiSchema Items { get; set; } + /// + public IOpenApiSchema Not { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxItems { get; set; } + /// + public ISet Required { get; set; } = new HashSet(); - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinItems { get; set; } + /// + public IOpenApiSchema Items { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? UniqueItems { get; set; } + /// + public int? MaxItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Property definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced). - /// - public virtual IDictionary Properties { get; set; } = new Dictionary(); + /// + public int? MinItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// PatternProperty definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced) - /// Each property name of this object SHOULD be a valid regular expression according to the ECMA 262 r - /// egular expression dialect. Each property value of this object MUST be an object, and each object MUST - /// be a valid Schema Object not a standard JSON Schema. - /// - public virtual IDictionary PatternProperties { get; set; } = new Dictionary(); + /// + public bool? UniqueItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxProperties { get; set; } + /// + public IDictionary Properties { get; set; } = new Dictionary(StringComparer.Ordinal); - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinProperties { get; set; } + /// + public IDictionary PatternProperties { get; set; } = new Dictionary(StringComparer.Ordinal); - /// - /// Indicates if the schema can contain properties other than those defined by the properties map. - /// - public virtual bool AdditionalPropertiesAllowed { get; set; } = true; + /// + public int? MaxProperties { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value can be boolean or object. Inline or referenced schema - /// MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual OpenApiSchema AdditionalProperties { get; set; } + /// + public int? MinProperties { get; set; } - /// - /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate - /// between other schemas which may satisfy the payload description. - /// - public virtual OpenApiDiscriminator Discriminator { get; set; } + /// + public bool AdditionalPropertiesAllowed { get; set; } = true; - /// - /// A free-form property to include an example of an instance for this schema. - /// To represent examples that cannot be naturally represented in JSON or YAML, - /// a string value can be used to contain the example with escaping where necessary. - /// - public virtual JsonNode Example { get; set; } + /// + public IOpenApiSchema AdditionalProperties { get; set; } - /// - /// A free-form property to include examples of an instance for this schema. - /// To represent examples that cannot be naturally represented in JSON or YAML, - /// a list of values can be used to contain the examples with escaping where necessary. - /// - public virtual IList Examples { get; set; } + /// + public OpenApiDiscriminator Discriminator { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual IList Enum { get; set; } = new List(); + /// + public JsonNode Example { get; set; } - /// - /// Allows sending a null value for the defined schema. Default value is false. - /// - public virtual bool Nullable { get; set; } + /// + public IList Examples { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool UnevaluatedProperties { get; set;} + /// + public IList Enum { get; set; } = new List(); - /// - /// Additional external documentation for this schema. - /// - public virtual OpenApiExternalDocs ExternalDocs { get; set; } + /// + public bool Nullable { get; set; } - /// - /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage. - /// Default value is false. - /// - public virtual bool Deprecated { get; set; } + /// + public bool UnevaluatedProperties { get; set;} - /// - /// This MAY be used only on properties schemas. It has no effect on root schemas. - /// Adds additional metadata to describe the XML representation of this property. - /// - public virtual OpenApiXml Xml { get; set; } + /// + public OpenApiExternalDocs ExternalDocs { get; set; } - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public bool Deprecated { get; set; } - /// - /// This object stores any unrecognized keywords found in the schema. - /// - public virtual IDictionary UnrecognizedKeywords { get; set; } = new Dictionary(); + /// + public OpenApiXml Xml { get; set; } - /// - /// Indicates object is a placeholder reference to an actual object and does not contain valid data. - /// - public virtual bool UnresolvedReference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); - /// - /// Reference object. - /// - public virtual OpenApiReference Reference { get; set; } + /// + public IDictionary UnrecognizedKeywords { get; set; } = new Dictionary(); /// public IDictionary Annotations { get; set; } @@ -335,9 +183,10 @@ public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiRe public OpenApiSchema() { } /// - /// Initializes a copy of object + /// Initializes a copy of object /// - public OpenApiSchema(OpenApiSchema schema) + /// The schema object to copy from. + public OpenApiSchema(IOpenApiSchema schema) { Title = schema?.Title ?? Title; Id = schema?.Id ?? Id; @@ -347,7 +196,7 @@ public OpenApiSchema(OpenApiSchema schema) Vocabulary = schema?.Vocabulary != null ? new Dictionary(schema.Vocabulary) : null; DynamicAnchor = schema?.DynamicAnchor ?? DynamicAnchor; DynamicRef = schema?.DynamicRef ?? DynamicRef; - Definitions = schema?.Definitions != null ? new Dictionary(schema.Definitions) : null; + Definitions = schema?.Definitions != null ? new Dictionary(schema.Definitions) : null; UnevaluatedProperties = schema?.UnevaluatedProperties ?? UnevaluatedProperties; V31ExclusiveMaximum = schema?.V31ExclusiveMaximum ?? V31ExclusiveMaximum; V31ExclusiveMinimum = schema?.V31ExclusiveMinimum ?? V31ExclusiveMinimum; @@ -365,21 +214,21 @@ public OpenApiSchema(OpenApiSchema schema) Default = schema?.Default != null ? JsonNodeCloneHelper.Clone(schema?.Default) : null; ReadOnly = schema?.ReadOnly ?? ReadOnly; WriteOnly = schema?.WriteOnly ?? WriteOnly; - AllOf = schema?.AllOf != null ? new List(schema.AllOf) : null; - OneOf = schema?.OneOf != null ? new List(schema.OneOf) : null; - AnyOf = schema?.AnyOf != null ? new List(schema.AnyOf) : null; - Not = schema?.Not != null ? new(schema?.Not) : null; + AllOf = schema?.AllOf != null ? new List(schema.AllOf) : null; + OneOf = schema?.OneOf != null ? new List(schema.OneOf) : null; + AnyOf = schema?.AnyOf != null ? new List(schema.AnyOf) : null; + Not = schema?.Not != null ? new OpenApiSchema(schema?.Not) : null; Required = schema?.Required != null ? new HashSet(schema.Required) : null; - Items = schema?.Items != null ? new(schema?.Items) : null; + Items = schema?.Items != null ? new OpenApiSchema(schema?.Items) : null; MaxItems = schema?.MaxItems ?? MaxItems; MinItems = schema?.MinItems ?? MinItems; UniqueItems = schema?.UniqueItems ?? UniqueItems; - Properties = schema?.Properties != null ? new Dictionary(schema.Properties) : null; - PatternProperties = schema?.PatternProperties != null ? new Dictionary(schema.PatternProperties) : null; + Properties = schema?.Properties != null ? new Dictionary(schema.Properties) : null; + PatternProperties = schema?.PatternProperties != null ? new Dictionary(schema.PatternProperties) : null; MaxProperties = schema?.MaxProperties ?? MaxProperties; MinProperties = schema?.MinProperties ?? MinProperties; AdditionalPropertiesAllowed = schema?.AdditionalPropertiesAllowed ?? AdditionalPropertiesAllowed; - AdditionalProperties = schema?.AdditionalProperties != null ? new(schema?.AdditionalProperties) : null; + AdditionalProperties = schema?.AdditionalProperties != null ? new OpenApiSchema(schema?.AdditionalProperties) : null; Discriminator = schema?.Discriminator != null ? new(schema?.Discriminator) : null; Example = schema?.Example != null ? JsonNodeCloneHelper.Clone(schema?.Example) : null; Examples = schema?.Examples != null ? new List(schema.Examples) : null; @@ -389,24 +238,18 @@ public OpenApiSchema(OpenApiSchema schema) Deprecated = schema?.Deprecated ?? Deprecated; Xml = schema?.Xml != null ? new(schema?.Xml) : null; Extensions = schema?.Extensions != null ? new Dictionary(schema.Extensions) : null; - UnresolvedReference = schema?.UnresolvedReference ?? UnresolvedReference; - Reference = schema?.Reference != null ? new(schema?.Reference) : null; Annotations = schema?.Annotations != null ? new Dictionary(schema?.Annotations) : null; UnrecognizedKeywords = schema?.UnrecognizedKeywords != null ? new Dictionary(schema?.UnrecognizedKeywords) : null; } - /// - /// Serialize to Open Api v3.1 - /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } - /// - /// Serialize to Open Api v3.0 - /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + /// + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } @@ -551,9 +394,8 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version writer.WriteEndObject(); } -/// - - public virtual void SerializeAsV2(IOpenApiWriter writer) + /// + public void SerializeAsV2(IOpenApiWriter writer) { SerializeAsV2(writer: writer, parentRequiredProperties: new HashSet(), propertyName: null); } @@ -654,7 +496,7 @@ private void WriteFormatProperty(IOpenApiWriter writer) /// The open api writer. /// The list of required properties in parent schema. /// The property name that will be serialized. - internal virtual void SerializeAsV2( + private void SerializeAsV2( IOpenApiWriter writer, ISet parentRequiredProperties, string propertyName) @@ -745,7 +587,12 @@ internal virtual void SerializeAsV2( // properties writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, key, s) => - s.SerializeAsV2(w, Required, key)); + { + if (s is OpenApiSchema oais) + oais.SerializeAsV2(w, Required, key); + else + s.SerializeAsV2(w); + }); // additionalProperties if (AdditionalPropertiesAllowed) diff --git a/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs index d7205f37c..9b8c1be28 100644 --- a/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs +++ b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs @@ -10,7 +10,7 @@ namespace Microsoft.OpenApi.Models.References; /// The interface type for the model. public abstract class BaseOpenApiReferenceHolder : IOpenApiReferenceHolder where T : class, IOpenApiReferenceable, V where V : IOpenApiSerializable { - internal T _target; + private T _target; /// public T Target { @@ -72,7 +72,7 @@ protected BaseOpenApiReferenceHolder(string referenceId, OpenApiDocument hostDoc /// public abstract V CopyReferenceAsTargetElementWithOverrides(V source); /// - public void SerializeAsV3(IOpenApiWriter writer) + public virtual void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { @@ -85,7 +85,7 @@ public void SerializeAsV3(IOpenApiWriter writer) } /// - public void SerializeAsV31(IOpenApiWriter writer) + public virtual void SerializeAsV31(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs index dfbee5ce7..bca77ff29 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs @@ -64,7 +64,7 @@ public string Description public bool AllowEmptyValue { get => Target?.AllowEmptyValue ?? default; } /// - public OpenApiSchema Schema { get => Target?.Schema; } + public IOpenApiSchema Schema { get => Target?.Schema; } /// public ParameterStyle? Style { get => Target?.Style; } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs index 82c73afda..0f5137cf3 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs @@ -68,7 +68,7 @@ public string Description public bool AllowReserved { get => Target?.AllowReserved ?? default; } /// - public OpenApiSchema Schema { get => Target?.Schema; } + public IOpenApiSchema Schema { get => Target?.Schema; } /// public IDictionary Examples { get => Target?.Examples; } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs index 731f9c1af..d31ba1950 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; using System; using System.Collections.Generic; @@ -12,79 +13,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Schema reference object /// - public class OpenApiSchemaReference : OpenApiSchema, IOpenApiReferenceHolder + public class OpenApiSchemaReference : BaseOpenApiReferenceHolder, IOpenApiSchema { -#nullable enable - private OpenApiSchema? _target; - private readonly OpenApiReference _reference; - private string? _description; - private JsonNode? _default; - private JsonNode? _example; - private IList? _examples; - private bool? _nullable; - private IDictionary? _properties; - private string? _title; - private string? _schema; - private string? _comment; - private string? _id; - private string? _dynamicRef; - private string? _dynamicAnchor; - private IDictionary? _vocabulary; - private IDictionary? _definitions; - private decimal? _v31ExclusiveMaximum; - private decimal? _v31ExclusiveMinimum; - private bool? _unEvaluatedProperties; - private JsonSchemaType? _type; - private string? _const; - private string? _format; - private decimal? _maximum; - private bool? _exclusiveMaximum; - private decimal? _minimum; - private bool? _exclusiveMinimum; - private int? _maxLength; - private int? _minLength; - private string? _pattern; - private decimal? _multipleOf; - private bool? _readOnly; - private bool? _writeOnly; - private IList? _allOf; - private IList? _oneOf; - private IList? _anyOf; - private OpenApiSchema? _not; - private ISet? _required; - private OpenApiSchema _items; - private int? _maxItems; - private int? _minItems; - private bool? _uniqueItems; - private IDictionary? _patternProperties; - private int? _maxProperties; - private int? _minProperties; - private bool? _additionalPropertiesAllowed; - private OpenApiSchema? _additionalProperties; - private OpenApiDiscriminator? _discriminator; - private OpenApiExternalDocs? _externalDocs; - private bool? _deprecated; - private OpenApiXml? _xml; - private IDictionary? _extensions; - private bool? _unevaluatedProperties; - private IList? _enum; - - /// - /// Gets the target schema. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiSchema? Target -#nullable restore - { - get - { - _target ??= Reference.HostDocument?.ResolveReferenceTo(_reference); - return _target; - } - } - /// /// Constructor initializing the reference object. /// @@ -95,214 +25,173 @@ public OpenApiSchema? Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiSchemaReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiSchemaReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Schema, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Schema, - ExternalResource = externalResource - }; - - Reference = _reference; } - internal OpenApiSchemaReference(OpenApiSchema target, string referenceId) + internal OpenApiSchemaReference(OpenApiSchema target, string referenceId):base(target, referenceId, ReferenceType.Schema) { - _target = target; + } - _reference = new OpenApiReference() + /// + public string Description + { + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set { - Id = referenceId, - Type = ReferenceType.Schema, - }; + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override string Title { get => string.IsNullOrEmpty(_title) ? Target?.Title : _title; set => _title = value; } + public string Title { get => Target?.Title; } /// - public override string Schema { get => string.IsNullOrEmpty(_schema) ? Target?.Schema : _schema; set => _schema = value; } + public string Schema { get => Target?.Schema; } /// - public override string Id { get => string.IsNullOrEmpty(_id) ? Target?.Id : _id; set => _id = value; } + public string Id { get => Target?.Id; } /// - public override string Comment { get => string.IsNullOrEmpty(_comment) ? Target?.Comment : _comment; set => _comment = value; } + public string Comment { get => Target?.Comment; } /// - public override IDictionary Vocabulary { get => _vocabulary is not null ? _vocabulary : Target?.Vocabulary; set => _vocabulary = value; } + public IDictionary Vocabulary { get => Target?.Vocabulary; } /// - public override string DynamicRef { get => string.IsNullOrEmpty(_dynamicRef) ? Target?.DynamicRef : _dynamicRef; set => _dynamicRef = value; } + public string DynamicRef { get => Target?.DynamicRef; } /// - public override string DynamicAnchor { get => string.IsNullOrEmpty(_dynamicAnchor) ? Target?.DynamicAnchor : _dynamicAnchor; set => _dynamicAnchor = value; } + public string DynamicAnchor { get => Target?.DynamicAnchor; } /// - public override IDictionary Definitions { get => _definitions is not null ? _definitions : Target?.Definitions; set => _definitions = value; } + public IDictionary Definitions { get => Target?.Definitions; } /// - public override decimal? V31ExclusiveMaximum { get => _v31ExclusiveMaximum is not null ? _v31ExclusiveMaximum.Value : Target?.V31ExclusiveMaximum; set => _v31ExclusiveMaximum = value; } + public decimal? V31ExclusiveMaximum { get => Target?.V31ExclusiveMaximum; } /// - public override decimal? V31ExclusiveMinimum { get => _v31ExclusiveMinimum is not null ? _v31ExclusiveMinimum.Value : Target?.V31ExclusiveMinimum; set => _v31ExclusiveMinimum = value; } + public decimal? V31ExclusiveMinimum { get => Target?.V31ExclusiveMinimum; } /// - public override bool UnEvaluatedProperties { get => _unEvaluatedProperties is not null ? _unEvaluatedProperties.Value : Target?.UnEvaluatedProperties ?? false; set => _unEvaluatedProperties = value; } + public bool UnEvaluatedProperties { get => Target?.UnEvaluatedProperties ?? false; } /// - public override JsonSchemaType? Type { get => _type is not null ? _type.Value : Target?.Type; set => _type = value; } + public JsonSchemaType? Type { get => Target?.Type; } /// - public override string Const { get => string.IsNullOrEmpty(_const) ? Target?.Const : _const; set => _const = value; } + public string Const { get => Target?.Const; } /// - public override string Format { get => string.IsNullOrEmpty(_format) ? Target?.Format : _format; set => _format = value; } + public string Format { get => Target?.Format; } /// - public override string Description - { - get => string.IsNullOrEmpty(_description) ? Target?.Description : _description; - set => _description = value; - } + public decimal? Maximum { get => Target?.Maximum; } + /// + public bool? ExclusiveMaximum { get => Target?.ExclusiveMaximum; } /// - public override decimal? Maximum { get => _maximum is not null ? _maximum : Target?.Maximum; set => _maximum = value; } + public decimal? Minimum { get => Target?.Minimum; } /// - public override bool? ExclusiveMaximum { get => _exclusiveMaximum is not null ? _exclusiveMaximum : Target?.ExclusiveMaximum; set => _exclusiveMaximum = value; } + public bool? ExclusiveMinimum { get => Target?.ExclusiveMinimum; } /// - public override decimal? Minimum { get => _minimum is not null ? _minimum : Target?.Minimum; set => _minimum = value; } + public int? MaxLength { get => Target?.MaxLength; } /// - public override bool? ExclusiveMinimum { get => _exclusiveMinimum is not null ? _exclusiveMinimum : Target?.ExclusiveMinimum; set => _exclusiveMinimum = value; } + public int? MinLength { get => Target?.MinLength; } /// - public override int? MaxLength { get => _maxLength is not null ? _maxLength : Target?.MaxLength; set => _maxLength = value; } + public string Pattern { get => Target?.Pattern; } /// - public override int? MinLength { get => _minLength is not null ? _minLength : Target?.MinLength; set => _minLength = value; } + public decimal? MultipleOf { get => Target?.MultipleOf; } /// - public override string Pattern { get => string.IsNullOrEmpty(_pattern) ? Target?.Pattern : _pattern; set => _pattern = value; } + public JsonNode Default { get => Target?.Default; } /// - public override decimal? MultipleOf { get => _multipleOf is not null ? _multipleOf : Target?.MultipleOf; set => _multipleOf = value; } + public bool ReadOnly { get => Target?.ReadOnly ?? false; } /// - public override JsonNode Default { get => _default is not null ? _default : Target?.Default; set => _default = value; } + public bool WriteOnly { get => Target?.WriteOnly ?? false; } /// - public override bool ReadOnly { get => _readOnly is not null ? _readOnly.Value : Target?.ReadOnly ?? false; set => _readOnly = value; } + public IList AllOf { get => Target?.AllOf; } /// - public override bool WriteOnly { get => _writeOnly is not null ? _writeOnly.Value : Target?.WriteOnly ?? false; set => _writeOnly = value; } + public IList OneOf { get => Target?.OneOf; } /// - public override IList AllOf { get => _allOf is not null ? _allOf : Target?.AllOf; set => _allOf = value; } + public IList AnyOf { get => Target?.AnyOf; } /// - public override IList OneOf { get => _oneOf is not null ? _oneOf : Target?.OneOf; set => _oneOf = value; } + public IOpenApiSchema Not { get => Target?.Not; } /// - public override IList AnyOf { get => _anyOf is not null ? _anyOf : Target?.AnyOf; set => _anyOf = value; } + public ISet Required { get => Target?.Required; } /// - public override OpenApiSchema Not { get => _not is not null ? _not : Target?.Not; set => _not = value; } + public IOpenApiSchema Items { get => Target?.Items; } /// - public override ISet Required { get => _required is not null ? _required : Target?.Required; set => _required = value; } + public int? MaxItems { get => Target?.MaxItems; } /// - public override OpenApiSchema Items { get => _items is not null ? _items : Target?.Items; set => _items = value; } + public int? MinItems { get => Target?.MinItems; } /// - public override int? MaxItems { get => _maxItems is not null ? _maxItems : Target?.MaxItems; set => _maxItems = value; } + public bool? UniqueItems { get => Target?.UniqueItems; } /// - public override int? MinItems { get => _minItems is not null ? _minItems : Target?.MinItems; set => _minItems = value; } + public IDictionary Properties { get => Target?.Properties; } /// - public override bool? UniqueItems { get => _uniqueItems is not null ? _uniqueItems : Target?.UniqueItems; set => _uniqueItems = value; } + public IDictionary PatternProperties { get => Target?.PatternProperties; } /// - public override IDictionary Properties { get => _properties is not null ? _properties : Target?.Properties; set => _properties = value; } + public int? MaxProperties { get => Target?.MaxProperties; } /// - public override IDictionary PatternProperties { get => _patternProperties is not null ? _patternProperties : Target?.PatternProperties; set => _patternProperties = value; } + public int? MinProperties { get => Target?.MinProperties; } /// - public override int? MaxProperties { get => _maxProperties is not null ? _maxProperties : Target?.MaxProperties; set => _maxProperties = value; } + public bool AdditionalPropertiesAllowed { get => Target?.AdditionalPropertiesAllowed ?? true; } /// - public override int? MinProperties { get => _minProperties is not null ? _minProperties : Target?.MinProperties; set => _minProperties = value; } + public IOpenApiSchema AdditionalProperties { get => Target?.AdditionalProperties; } /// - public override bool AdditionalPropertiesAllowed { get => _additionalPropertiesAllowed is not null ? _additionalPropertiesAllowed.Value : Target?.AdditionalPropertiesAllowed ?? true; set => _additionalPropertiesAllowed = value; } + public OpenApiDiscriminator Discriminator { get => Target?.Discriminator; } /// - public override OpenApiSchema AdditionalProperties { get => _additionalProperties is not null ? _additionalProperties : Target?.AdditionalProperties; set => _additionalProperties = value; } + public JsonNode Example { get => Target?.Example; } /// - public override OpenApiDiscriminator Discriminator { get => _discriminator is not null ? _discriminator : Target?.Discriminator; set => _discriminator = value; } + public IList Examples { get => Target?.Examples; } /// - public override JsonNode Example { get => _example is not null ? _example : Target?.Example; set => _example = value; } + public IList Enum { get => Target?.Enum; } /// - public override IList Examples { get => _examples is not null ? _examples : Target?.Examples; set => _examples = value; } + public bool Nullable { get => Target?.Nullable ?? false; } /// - public override IList Enum { get => _enum is not null ? _enum : Target?.Enum; set => _enum = value; } + public bool UnevaluatedProperties { get => Target?.UnevaluatedProperties ?? false; } /// - public override bool Nullable { get => _nullable is not null ? _nullable.Value : Target?.Nullable ?? false; set => _nullable = value; } + public OpenApiExternalDocs ExternalDocs { get => Target?.ExternalDocs; } /// - public override bool UnevaluatedProperties { get => _unevaluatedProperties is not null ? _unevaluatedProperties.Value : Target?.UnevaluatedProperties ?? false; set => _unevaluatedProperties = value; } + public bool Deprecated { get => Target?.Deprecated ?? false; } /// - public override OpenApiExternalDocs ExternalDocs { get => _externalDocs is not null ? _externalDocs : Target?.ExternalDocs; set => _externalDocs = value; } + public OpenApiXml Xml { get => Target?.Xml; } /// - public override bool Deprecated { get => _deprecated is not null ? _deprecated.Value : Target?.Deprecated ?? false; set => _deprecated = value; } + public IDictionary Extensions { get => Target?.Extensions; } + /// - public override OpenApiXml Xml { get => _xml is not null ? _xml : Target?.Xml; set => _xml = value; } + public IDictionary UnrecognizedKeywords { get => Target?.UnrecognizedKeywords; } + /// - public override IDictionary Extensions { get => _extensions is not null ? _extensions : Target?.Extensions; set => _extensions = value; } + public IDictionary Annotations { get => Target?.Annotations; } /// public override void SerializeAsV31(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - // If Loop is detected then just Serialize as a reference. - else if (!writer.GetSettings().LoopDetector.PushLoop(this)) - { - writer.GetSettings().LoopDetector.SaveLoop(this); - _reference.SerializeAsV31(writer); - return; - } - - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - writer.GetSettings().LoopDetector.PopLoop(); + SerializeAsWithoutLoops(writer, (w, element) => (element is IOpenApiSchema s ? CopyReferenceAsTargetElementWithOverrides(s) : element).SerializeAsV3(w)); } /// public override void SerializeAsV3(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - // If Loop is detected then just Serialize as a reference. - else if (!writer.GetSettings().LoopDetector.PushLoop(this)) - { - writer.GetSettings().LoopDetector.SaveLoop(this); - _reference.SerializeAsV3(writer); - return; - } - - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - writer.GetSettings().LoopDetector.PopLoop(); + SerializeAsWithoutLoops(writer, (w, element) => element.SerializeAsV3(w)); } - /// - internal override void SerializeAsV2( - IOpenApiWriter writer, - ISet parentRequiredProperties, - string propertyName) + public override void SerializeAsV2(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - } - else - { - base.SerializeAsV2(writer, parentRequiredProperties, propertyName); - } + SerializeAsWithoutLoops(writer, (w, element) => element.SerializeAsV2(w)); } - - /// - public override void SerializeAsV2(IOpenApiWriter writer) + private void SerializeAsWithoutLoops(IOpenApiWriter writer, Action action) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (!writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV2(writer); + action(writer, Reference); + } + // If Loop is detected then just Serialize as a reference. + else if (!writer.GetSettings().LoopDetector.PushLoop(this)) + { + writer.GetSettings().LoopDetector.SaveLoop(this); + action(writer, Reference); } else { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); + SerializeInternal(writer, (w, element) => action(w, element)); + writer.GetSettings().LoopDetector.PopLoop(); } - } + } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public override IOpenApiSchema CopyReferenceAsTargetElementWithOverrides(IOpenApiSchema source) { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return source is OpenApiSchema ? new OpenApiSchema(this) : source; } } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs index 92dd24138..16456c400 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs @@ -4,6 +4,7 @@ using System; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.ParseNodes { @@ -15,7 +16,7 @@ internal class AnyFieldMapParameter public AnyFieldMapParameter( Func propertyGetter, Action propertySetter, - Func SchemaGetter = null) + Func SchemaGetter = null) { this.PropertyGetter = propertyGetter; this.PropertySetter = propertySetter; @@ -35,6 +36,6 @@ public AnyFieldMapParameter( /// /// Function to get the schema to apply to the property. /// - public Func SchemaGetter { get; } + public Func SchemaGetter { get; } } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs index 4d365125b..52397aed9 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.ParseNodes { @@ -17,7 +18,7 @@ public AnyMapFieldMapParameter( Func> propertyMapGetter, Func propertyGetter, Action propertySetter, - Func schemaGetter) + Func schemaGetter) { this.PropertyMapGetter = propertyMapGetter; this.PropertyGetter = propertyGetter; @@ -43,6 +44,6 @@ public AnyMapFieldMapParameter( /// /// Function to get the schema to apply to the property. /// - public Func SchemaGetter { get; } + public Func SchemaGetter { get; } } } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs index bc2333e46..cd31ef678 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs @@ -95,12 +95,15 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static OpenApiSchema GetOrCreateSchema(OpenApiHeader p) { - return p.Schema ??= new(); + return p.Schema switch { + OpenApiSchema schema => schema, + _ => (OpenApiSchema)(p.Schema = new OpenApiSchema()), + }; } public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) @@ -113,7 +116,7 @@ public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocu property.ParseField(header, _headerFixedFields, _headerPatternFields, hostDocument); } - var schema = node.Context.GetFromTempStorage("schema"); + var schema = node.Context.GetFromTempStorage("schema"); if (schema != null) { header.Schema = schema; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs index 140ad9f3d..7aa6f2bd5 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs @@ -9,6 +9,7 @@ using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Models.Interfaces; +using System; namespace Microsoft.OpenApi.Reader.V2 { @@ -147,18 +148,20 @@ private static OpenApiRequestBody CreateFormBody(ParsingContext context, List k.Name, - v => + v => { - var schema = v.Schema; - schema.Description = v.Description; - schema.Extensions = v.Extensions; - return schema; + var schema = new OpenApiSchema(v.Schema) + { + Description = v.Description, + Extensions = v.Extensions + }; + return (IOpenApiSchema)schema; }), - Required = new HashSet(formParameters.Where(p => p.Required).Select(p => p.Name)) + Required = new HashSet(formParameters.Where(static p => p.Required).Select(static p => p.Name), StringComparer.Ordinal) } }; @@ -173,8 +176,8 @@ private static OpenApiRequestBody CreateFormBody(ParsingContext context, List mediaType) }; - foreach (var value in formBody.Content.Values.Where(static x => x.Schema is not null && x.Schema.Properties.Any() && x.Schema.Type == null)) - value.Schema.Type = JsonSchemaType.Object; + foreach (var value in formBody.Content.Values.Where(static x => x.Schema is not null && x.Schema.Properties.Any() && x.Schema.Type == null).Select(static x => x.Schema).OfType()) + value.Type = JsonSchemaType.Object; return formBody; } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs index 2153d37d2..00d6dbb9c 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs @@ -147,7 +147,10 @@ private static void LoadParameterExamplesExtension(OpenApiParameter parameter, P private static OpenApiSchema GetOrCreateSchema(OpenApiParameter p) { - return p.Schema ??= new(); + return p.Schema switch { + OpenApiSchema schema => schema, + _ => (OpenApiSchema)(p.Schema = new OpenApiSchema()), + }; } private static void ProcessIn(OpenApiParameter o, ParseNode n, OpenApiDocument hostDocument) @@ -208,7 +211,7 @@ public static IOpenApiParameter LoadParameter(ParseNode node, bool loadRequestBo ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields, doc: hostDocument); - var schema = node.Context.GetFromTempStorage("schema"); + var schema = node.Context.GetFromTempStorage("schema"); if (schema != null) { parameter.Schema = schema; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs index d730c8227..1bc851852 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs @@ -74,7 +74,7 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P ?? context.GetFromTempStorage>(TempStorageKeys.GlobalProduces) ?? context.DefaultContentType ?? new List { "application/octet-stream" }; - var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response); + var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response); var examples = context.GetFromTempStorage>(TempStorageKeys.Examples, response) ?? new Dictionary(); @@ -171,7 +171,7 @@ private static void LoadExample(OpenApiResponse response, string mediaType, Pars { mediaTypeObject = new() { - Schema = node.Context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response) + Schema = node.Context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response) }; response.Content.Add(mediaType, mediaTypeObject); } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs index 78453f9d2..1c379d008 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs @@ -7,6 +7,8 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; +using Microsoft.OpenApi.Models.Interfaces; +using System; namespace Microsoft.OpenApi.Reader.V2 { @@ -153,10 +155,10 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("schema"); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs index bad6d04b8..23828348f 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs @@ -3,8 +3,10 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; +using System; using System.Collections.Generic; using System.Globalization; @@ -171,10 +173,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode(OpenApiConstants.Schema); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs index 87ecc8f00..a78ca14e1 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs @@ -3,8 +3,10 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -236,10 +238,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode(OpenApiConstants.Schema); diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index 6fbcbcc4a..490c7cff8 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -89,9 +89,9 @@ private void AddSchemaToComponents(OpenApiSchema schema, string referenceId = nu { EnsureComponentsExist(); EnsureSchemasExist(); - if (!Components.Schemas.ContainsKey(referenceId ?? schema.Reference.Id)) + if (!Components.Schemas.ContainsKey(referenceId)) { - Components.Schemas.Add(referenceId ?? schema.Reference.Id, schema); + Components.Schemas.Add(referenceId, schema); } } @@ -179,17 +179,13 @@ private void AddSecuritySchemeToComponents(OpenApiSecurityScheme securityScheme, } /// - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { // This is needed to handle schemas used in Responses in components if (schema is OpenApiSchemaReference openApiSchemaReference) { AddSchemaToComponents(openApiSchemaReference.Target, openApiSchemaReference.Reference.Id); } - else if (schema.Reference != null) - { - AddSchemaToComponents(schema); - } base.Visit(schema); } @@ -200,7 +196,7 @@ private void EnsureComponentsExist() private void EnsureSchemasExist() { - _target.Components.Schemas ??= new Dictionary(); + _target.Components.Schemas ??= new Dictionary(); } private void EnsureParametersExist() diff --git a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs index b2eb9eab1..2b79864d8 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs @@ -230,9 +230,9 @@ public virtual void Visit(OpenApiExternalDocs externalDocs) } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiSchema schema) + public virtual void Visit(IOpenApiSchema schema) { } diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index 41d7561ab..8d634834a 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.Services public class OpenApiWalker { private readonly OpenApiVisitorBase _visitor; - private readonly Stack _schemaLoop = new(); + private readonly Stack _schemaLoop = new(); private readonly Stack _pathItemLoop = new(); /// @@ -864,11 +864,11 @@ internal void Walk(OpenApiEncoding encoding) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiSchema schema, bool isComponent = false) + internal void Walk(IOpenApiSchema schema, bool isComponent = false) { - if (schema == null || ProcessAsReference(schema, isComponent)) + if (schema == null || schema is IOpenApiReferenceHolder holder && ProcessAsReference(holder, isComponent)) { return; } @@ -1012,9 +1012,9 @@ internal void Walk(IList examples) } /// - /// Visits a list of and child objects + /// Visits a list of and child objects /// - internal void Walk(IList schemas) + internal void Walk(IList schemas) { if (schemas == null) { diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index 0e1251d2e..a8669fce0 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -108,7 +108,7 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(IOpenApiParameter parameter) => Validate(parameter); /// - public override void Visit(OpenApiSchema schema) => Validate(schema); + public override void Visit(IOpenApiSchema schema) => Validate(schema); /// public override void Visit(OpenApiServer server) => Validate(server); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs index 1d38af4ce..03661401c 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs @@ -47,7 +47,7 @@ public static class OpenApiNonDefaultRules /// /// Validate the data matches with the given data type. /// - public static ValidationRule SchemaMismatchedDataType => + public static ValidationRule SchemaMismatchedDataType => new(nameof(SchemaMismatchedDataType), (context, schema) => { @@ -91,7 +91,7 @@ private static void ValidateMismatchedDataType(IValidationContext context, string ruleName, JsonNode example, IDictionary examples, - OpenApiSchema schema) + IOpenApiSchema schema) { // example context.Enter("example"); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs index 054c79c6b..b954c96b6 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -16,14 +18,14 @@ public static class OpenApiSchemaRules /// /// Validates Schema Discriminator /// - public static ValidationRule ValidateSchemaDiscriminator => + public static ValidationRule ValidateSchemaDiscriminator => new(nameof(ValidateSchemaDiscriminator), (context, schema) => { // discriminator context.Enter("discriminator"); - if (schema.Reference != null && schema.Discriminator != null) + if (schema is not null && schema.Discriminator != null) { var discriminatorName = schema.Discriminator?.PropertyName; @@ -31,7 +33,7 @@ public static class OpenApiSchemaRules { context.CreateError(nameof(ValidateSchemaDiscriminator), string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator, - schema.Reference.Id, discriminatorName)); + schema is OpenApiSchemaReference { Reference: not null} schemaReference ? schemaReference.Reference.Id : string.Empty, discriminatorName)); } } @@ -44,7 +46,7 @@ public static class OpenApiSchemaRules /// The parent schema. /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate /// between other schemas which may satisfy the payload description. - public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema, string discriminatorName) + public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema, string discriminatorName) { if (!schema.Required?.Contains(discriminatorName) ?? false) { @@ -77,7 +79,7 @@ public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema, /// between other schemas which may satisfy the payload description. /// The child schema. /// - public static bool TraverseSchemaElements(string discriminatorName, IList childSchema) + public static bool TraverseSchemaElements(string discriminatorName, IList childSchema) { foreach (var childItem in childSchema) { diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index 61b9d3a0c..62ab79406 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -5,6 +5,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Validations.Rules { @@ -44,7 +45,7 @@ public static void ValidateDataTypeMismatch( IValidationContext context, string ruleName, JsonNode value, - OpenApiSchema schema) + IOpenApiSchema schema) { if (schema == null) { diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs index abf7232d1..f868dfa07 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs @@ -122,10 +122,10 @@ private static OpenApiDocument GetSampleOpenApiDocument() "application/json", new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -149,20 +149,20 @@ private static OpenApiDocument GetSampleOpenApiDocument() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { { "TestSchema", new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "averageAudioDegradation", new OpenApiSchema { - AnyOf = new List + AnyOf = new List { - new() { Type = JsonSchemaType.Number }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number }, + new OpenApiSchema() { Type = JsonSchemaType.String } }, Format = "float", Nullable = true @@ -171,10 +171,10 @@ private static OpenApiDocument GetSampleOpenApiDocument() { "defaultPrice", new OpenApiSchema { - OneOf = new List + OneOf = new List { - new() { Type = JsonSchemaType.Number, Format = "double" }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double" }, + new OpenApiSchema() { Type = JsonSchemaType.String } } } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index ca4416ae6..a3494ba13 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -129,7 +129,7 @@ public void CreateFilteredDocumentUsingPredicateFromRequestUrl() Name = "id", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs index 0d25c7704..b5289c1ef 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs @@ -87,7 +87,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -106,7 +106,7 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -127,7 +127,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -152,7 +152,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -171,7 +171,7 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -191,7 +191,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -219,25 +219,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Title = "Collection of user", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "value", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.user" - } - } } } } @@ -273,14 +265,6 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.user" - } - } } } } @@ -325,7 +309,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Query, Required = true, Description = "Select properties to be returned", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -344,14 +328,6 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.message" - } - } } } } @@ -380,7 +356,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Required = true, Description = "key: id of administrativeUnit", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -399,11 +375,11 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { - AnyOf = new List + AnyOf = new List { - new() + new OpenApiSchema() { Type = JsonSchemaType.String } @@ -463,25 +439,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Title = "Collection of hostSecurityProfile", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "value", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.networkInterface" - } - } } } } @@ -513,7 +481,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Description = "key: id of call", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -561,7 +529,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Description = "key: id of group", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -578,7 +546,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Description = "key: id of event", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -602,13 +570,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { - Type = JsonSchemaType.Array, - Reference = new() + Properties = new Dictionary { - Type = ReferenceType.Schema, - Id = "microsoft.graph.event" + { + "value", + new OpenApiSchema + { + Type = JsonSchemaType.Array, + } + } } } } @@ -643,14 +615,14 @@ public static OpenApiDocument CreateOpenApiDocument() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { { "microsoft.graph.networkInterface", new OpenApiSchema { Title = "networkInterface", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "description", new OpenApiSchema @@ -726,6 +698,11 @@ public static OpenApiDocument CreateOpenApiDocument() document.Paths[communicationsCallsKeepAlivePath].Operations[OperationType.Post].Tags!.Add(new OpenApiTagReference("communications.Actions", document)); document.Paths[eventsDeltaPath].Operations[OperationType.Get].Tags!.Add(new OpenApiTagReference("groups.Functions", document)); document.Paths[refPath].Operations[OperationType.Get].Tags!.Add(new OpenApiTagReference("applications.directoryObject", document)); + ((OpenApiSchema)document.Paths[usersPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.user", document); + document.Paths[usersByIdPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema = new OpenApiSchemaReference("microsoft.graph.user", document); + document.Paths[messagesByIdPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema = new OpenApiSchemaReference("microsoft.graph.message", document); + ((OpenApiSchema)document.Paths[securityProfilesPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.networkInterface", document); + ((OpenApiSchema)document.Paths[eventsDeltaPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.event", document); return document; } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs index 8440e8df4..98cc4ed78 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs @@ -37,7 +37,7 @@ public async Task LoadParameterReference() In = ParameterLocation.Query, Description = "number of items to skip", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -92,41 +92,37 @@ public async Task LoadResponseAndSchemaReference() var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); var reference = new OpenApiResponseReference("GeneralError", result.Document); - // Assert - Assert.Equivalent( - new OpenApiResponse + var expected = new OpenApiResponse { Description = "General Error", Content = { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchemaReference(new OpenApiSchema() { Description = "Sample description", Required = new HashSet {"name" }, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String } }, - - Reference = new() - { - Type = ReferenceType.Schema, - Id = "SampleObject2", - HostDocument = result.Document - } - } + }, "SampleObject2") } } - }, reference - ); + }; + + ((OpenApiSchemaReference)expected.Content["application/json"].Schema).Reference.HostDocument = result.Document; + var actual = reference.Target; + + // Assert + Assert.Equivalent(expected, actual); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index 5993d4e2c..136c46892 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -10,6 +10,7 @@ using FluentAssertions.Equivalency; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Xunit; @@ -73,12 +74,12 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) { Schemas = { - ["sampleSchema"] = new() + ["sampleSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["sampleProperty"] = new() + ["sampleProperty"] = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = (decimal)100.54, @@ -106,7 +107,7 @@ public async Task ShouldParseProducesInAnyOrder() var okSchema = new OpenApiSchema { - Properties = new Dictionary + Properties = new Dictionary { { "id", new OpenApiSchema { @@ -119,7 +120,7 @@ public async Task ShouldParseProducesInAnyOrder() var errorSchema = new OpenApiSchema { - Properties = new Dictionary + Properties = new Dictionary { { "code", new OpenApiSchema { @@ -142,7 +143,7 @@ public async Task ShouldParseProducesInAnyOrder() var okMediaType = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("Item", result.Document) @@ -276,7 +277,7 @@ public async Task ShouldAssignSchemaToAllResponses() var responses = result.Document.Paths["/items"].Operations[OperationType.Get].Responses; foreach (var response in responses) { - var targetSchema = response.Key == "200" ? successSchema : errorSchema; + var targetSchema = response.Key == "200" ? (IOpenApiSchema)successSchema : errorSchema; var json = response.Value.Content["application/json"]; Assert.NotNull(json); @@ -294,9 +295,11 @@ public async Task ShouldAllowComponentsThatJustContainAReference() // Act var actual = (await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "ComponentRootReference.json"))).Document; var schema1 = actual.Components.Schemas["AllPets"]; - Assert.False(schema1.UnresolvedReference); - var schema2 = actual.ResolveReferenceTo(schema1.Reference); - if (schema2.UnresolvedReference && schema1.Reference.Id == schema2.Reference.Id) + var schema1Reference = Assert.IsType(schema1); + Assert.False(schema1Reference.UnresolvedReference); + var schema2 = actual.ResolveReferenceTo(schema1Reference.Reference); + Assert.IsType(schema2); + if (string.IsNullOrEmpty(schema1Reference.Reference.Id) || schema1Reference.UnresolvedReference) { // detected a cycle - this code gets triggered Assert.Fail("A cycle should not be detected"); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs index cc15d8427..1b1187a42 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs @@ -34,7 +34,7 @@ public void ParseHeaderWithDefaultShouldSucceed() header.Should().BeEquivalentTo( new OpenApiHeader { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", @@ -63,7 +63,7 @@ public void ParseHeaderWithEnumShouldSucceed() header.Should().BeEquivalentTo( new OpenApiHeader { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs index ce7382b65..13339332a 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs @@ -39,7 +39,7 @@ public class OpenApiOperationTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -72,7 +72,7 @@ public class OpenApiOperationTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -86,7 +86,7 @@ public class OpenApiOperationTests { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -216,10 +216,10 @@ public void ParseOperationWithResponseExamplesShouldSucceed() { ["application/json"] = new OpenApiMediaType() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -234,10 +234,10 @@ public void ParseOperationWithResponseExamplesShouldSucceed() }, ["application/xml"] = new OpenApiMediaType() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs index 1b6300faf..aa11d5137 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs @@ -57,7 +57,7 @@ public void ParsePathParameterShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -86,10 +86,10 @@ public void ParseQueryParameterShouldSucceed() Name = "id", Description = "ID of the object to fetch", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -121,7 +121,7 @@ public void ParseParameterWithNullLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -150,7 +150,7 @@ public void ParseParameterWithNoLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -204,7 +204,7 @@ public void ParseParameterWithUnknownLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -233,7 +233,7 @@ public void ParseParameterWithDefaultShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", @@ -260,7 +260,7 @@ public void ParseParameterWithEnumShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs index a86d84bdd..412a74dde 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs @@ -27,10 +27,10 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "ID of pet to use", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -53,7 +53,7 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -65,17 +65,17 @@ public class OpenApiPathItemTests { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -89,17 +89,17 @@ public class OpenApiPathItemTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -148,7 +148,7 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -159,7 +159,7 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "Name of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -171,22 +171,22 @@ public class OpenApiPathItemTests { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String }, - ["skill"] = new() + ["skill"] = new OpenApiSchema() { Description = "Updated skill of the pet", Type = JsonSchemaType.String @@ -200,22 +200,22 @@ public class OpenApiPathItemTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String }, - ["skill"] = new() + ["skill"] = new OpenApiSchema() { Description = "Updated skill of the pet", Type = JsonSchemaType.String @@ -249,11 +249,8 @@ public class OpenApiPathItemTests public void ParseBasicPathItemWithFormDataShouldSucceed() { // Arrange - MapNode node; - using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicPathItemWithFormData.yaml"))) - { - node = TestHelper.CreateYamlMapNode(stream); - } + using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicPathItemWithFormData.yaml")); + var node = TestHelper.CreateYamlMapNode(stream); // Act var pathItem = OpenApiV2Deserializer.LoadPathItem(node, new()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs index 1b36921d7..781b272e1 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs @@ -13,6 +13,7 @@ using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Readers.Tests.V2Tests { @@ -108,7 +109,7 @@ public void PropertiesReferenceShouldWork() var targetSchema = new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["prop1"] = new OpenApiSchema() { @@ -121,7 +122,7 @@ public void PropertiesReferenceShouldWork() var referenceSchema = new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["propA"] = new OpenApiSchemaReference(referenceId, workingDocument), } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs index cda7e35c3..9c391ceb2 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs @@ -38,7 +38,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { Schemas = { - ["petSchema"] = new() + ["petSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -46,42 +46,42 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPetSchema"] = new() + ["newPetSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -115,10 +115,10 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -130,7 +130,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -146,7 +146,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -154,7 +154,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -212,9 +212,9 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["petSchema"] = new() + ["petSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -222,42 +222,42 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPetSchema"] = new() + ["newPetSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -289,10 +289,10 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -304,7 +304,7 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -419,7 +419,7 @@ public async Task ParseDocumentWithPatternPropertiesInSchemaWorks() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["prop1"] = new OpenApiSchema { @@ -434,7 +434,7 @@ public async Task ParseDocumentWithPatternPropertiesInSchemaWorks() Type = JsonSchemaType.String } }, - PatternProperties = new Dictionary + PatternProperties = new Dictionary { ["^x-.*$"] = new OpenApiSchema { diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index abcaa9df6..50c506533 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -9,6 +9,7 @@ using FluentAssertions; using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Tests; using Microsoft.OpenApi.Writers; @@ -42,7 +43,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() Schema = "https://json-schema.org/draft/2020-12/schema", Description = "A representation of a person, company, organization, or place", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["fruits"] = new OpenApiSchema { @@ -57,7 +58,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() Type = JsonSchemaType.Array } }, - Definitions = new Dictionary + Definitions = new Dictionary { ["veggie"] = new OpenApiSchema { @@ -67,7 +68,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() "veggieName", "veggieLike" }, - Properties = new Dictionary + Properties = new Dictionary { ["veggieName"] = new OpenApiSchema { @@ -165,9 +166,9 @@ public async Task ParseV31SchemaShouldSucceed() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["one"] = new() + ["one"] = new OpenApiSchema() { Description = "type array", Type = JsonSchemaType.Integer | JsonSchemaType.String @@ -189,29 +190,29 @@ public async Task ParseAdvancedV31SchemaShouldSucceed() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["one"] = new() + ["one"] = new OpenApiSchema() { Description = "type array", Type = JsonSchemaType.Integer | JsonSchemaType.String }, - ["two"] = new() + ["two"] = new OpenApiSchema() { Description = "type 'null'", Type = JsonSchemaType.Null }, - ["three"] = new() + ["three"] = new OpenApiSchema() { Description = "type array including 'null'", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["four"] = new() + ["four"] = new OpenApiSchema() { Description = "array with no items", Type = JsonSchemaType.Array }, - ["five"] = new() + ["five"] = new OpenApiSchema() { Description = "singular example", Type = JsonSchemaType.String, @@ -220,37 +221,37 @@ public async Task ParseAdvancedV31SchemaShouldSucceed() "exampleValue" } }, - ["six"] = new() + ["six"] = new OpenApiSchema() { Description = "exclusiveMinimum true", V31ExclusiveMinimum = 10 }, - ["seven"] = new() + ["seven"] = new OpenApiSchema() { Description = "exclusiveMinimum false", Minimum = 10 }, - ["eight"] = new() + ["eight"] = new OpenApiSchema() { Description = "exclusiveMaximum true", V31ExclusiveMaximum = 20 }, - ["nine"] = new() + ["nine"] = new OpenApiSchema() { Description = "exclusiveMaximum false", Maximum = 20 }, - ["ten"] = new() + ["ten"] = new OpenApiSchema() { Description = "nullable string", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["eleven"] = new() + ["eleven"] = new OpenApiSchema() { Description = "x-nullable string", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["twelve"] = new() + ["twelve"] = new OpenApiSchema() { Description = "file/binary" } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs index 4476d23a8..5aabe43d3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs @@ -94,7 +94,7 @@ public async Task ParseCallbackWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -144,7 +144,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -180,7 +180,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -215,7 +215,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 1b8f26c64..d5ccec6cc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -32,7 +32,7 @@ public OpenApiDocumentTests() OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); } - private static async Task CloneAsync(T element) where T : IOpenApiSerializable + private static async Task CloneAsync(T element) where T : class, IOpenApiSerializable { using var stream = new MemoryStream(); var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); @@ -205,9 +205,9 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet1"] = new() + ["pet1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -215,48 +215,48 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -264,14 +264,14 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -331,10 +331,10 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -346,7 +346,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -362,7 +362,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -370,7 +370,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -474,7 +474,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -534,7 +534,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -591,9 +591,9 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet1"] = new() + ["pet1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -601,48 +601,48 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -650,14 +650,14 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -681,31 +681,20 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() }; // Create a clone of the schema to avoid modifying things in components. - var petSchema = await CloneAsync(components.Schemas["pet1"]); - petSchema.Reference = new() - { - Id = "pet1", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; - - var newPetSchema = await CloneAsync(components.Schemas["newPet"]); + var petSchemaSource = Assert.IsType(components.Schemas["pet1"]); + var petSchema = await CloneAsync(petSchemaSource); + var castPetSchema = Assert.IsType(petSchema); + var petSchemaReference = new OpenApiSchemaReference(castPetSchema, "pet1"); - newPetSchema.Reference = new() - { - Id = "newPet", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; + var newPetSchemaSource = Assert.IsType(components.Schemas["newPet"]); + var newPetSchema = await CloneAsync(newPetSchemaSource); + var castNewPetSchema = Assert.IsType(newPetSchema); + var newPetSchemaReference = new OpenApiSchemaReference(castNewPetSchema, "newPet"); - var errorModelSchema = await CloneAsync(components.Schemas["errorModel"]); - - errorModelSchema.Reference = new() - { - Id = "errorModel", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; + var errorModelSchemaSource = Assert.IsType(components.Schemas["errorModel"]); + var errorModelSchema = await CloneAsync(errorModelSchemaSource); + var castErrorModelSchema = Assert.IsType(errorModelSchema); + var errorModelSchemaReference = new OpenApiSchemaReference(castErrorModelSchema, "errorModel"); var tagReference1 = new OpenApiTagReference("tagName1", null); @@ -778,10 +767,10 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -793,7 +782,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -809,18 +798,18 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = petSchema + Items = petSchemaReference } }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = petSchema + Items = petSchemaReference } } } @@ -832,7 +821,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -843,7 +832,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -866,7 +855,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = newPetSchema + Schema = newPetSchemaReference } } }, @@ -879,7 +868,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference }, } }, @@ -890,7 +879,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -901,7 +890,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -938,7 +927,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -954,11 +943,11 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference }, ["application/xml"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference } } }, @@ -969,7 +958,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -980,7 +969,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -998,7 +987,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1018,7 +1007,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -1029,7 +1018,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -1069,8 +1058,12 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() tagReference1.Reference.HostDocument = expected; tagReference2.Reference.HostDocument = expected; + petSchemaReference.Reference.HostDocument = expected; + newPetSchemaReference.Reference.HostDocument = expected; + errorModelSchemaReference.Reference.HostDocument = expected; actual.Document.Should().BeEquivalentTo(expected, options => options + .IgnoringCyclicReferences() .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Reference) .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Reference.HostDocument) .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Target) @@ -1127,7 +1120,7 @@ public async Task HeaderParameterShouldAllowExample() Style = ParameterStyle.Simple, Explode = true, Example = "99391c7e-ad88-49ec-a2ad-99ddcb1f7721", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "uuid" @@ -1160,7 +1153,7 @@ public async Task HeaderParameterShouldAllowExample() } } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "uuid" @@ -1231,7 +1224,7 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() In = ParameterLocation.Query, Description = "Limit the number of pets returned", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs index c103db5d8..bee674bfc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs @@ -52,7 +52,7 @@ public async Task ParseAdvancedEncodingShouldSucceed() new OpenApiHeader() { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs index e10c78a25..2905266fc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs @@ -35,7 +35,7 @@ public async Task ParseMediaTypeWithExampleShouldSucceed() new OpenApiMediaType { Example = 5, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -66,7 +66,7 @@ public async Task ParseMediaTypeWithExamplesShouldSucceed() Value = 7.5 } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs index 22167e0ee..3d629a23b 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs @@ -56,7 +56,7 @@ public async Task ParseOperationWithParameterWithNoLocationShouldSucceed() Name = "username", Description = "The user name for login", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -67,7 +67,7 @@ public async Task ParseOperationWithParameterWithNoLocationShouldSucceed() Description = "The password for login in clear text", In = ParameterLocation.Query, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs index 17411a859..2ee63165c 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs @@ -41,7 +41,7 @@ public async Task ParsePathParameterShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -62,10 +62,10 @@ public async Task ParseQueryParameterShouldSucceed() Name = "id", Description = "ID of the object to fetch", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -87,10 +87,10 @@ public async Task ParseQueryParameterWithObjectTypeShouldSucceed() { In = ParameterLocation.Query, Name = "freeForm", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -118,7 +118,7 @@ public async Task ParseQueryParameterWithObjectTypeAndContentShouldSucceed() { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = @@ -128,11 +128,11 @@ public async Task ParseQueryParameterWithObjectTypeAndContentShouldSucceed() }, Properties = { - ["lat"] = new() + ["lat"] = new OpenApiSchema() { Type = JsonSchemaType.Number }, - ["long"] = new() + ["long"] = new OpenApiSchema() { Type = JsonSchemaType.Number } @@ -159,10 +159,10 @@ public async Task ParseHeaderParameterShouldSucceed() Required = true, Style = ParameterStyle.Simple, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64", @@ -185,7 +185,7 @@ public async Task ParseParameterWithNullLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -209,7 +209,7 @@ public async Task ParseParameterWithNoLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -233,7 +233,7 @@ public async Task ParseParameterWithUnknownLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -255,7 +255,7 @@ public async Task ParseParameterWithExampleShouldSucceed() Description = "username to fetch", Required = true, Example = (float)5.0, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -288,7 +288,7 @@ public async Task ParseParameterWithExamplesShouldSucceed() Value = (float) 7.5 } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -308,7 +308,7 @@ public void ParseParameterWithReferenceWorks() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchema diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs index 8d94822ef..2fd230a19 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs @@ -165,7 +165,7 @@ public void ParseDictionarySchemaShouldSucceed() new OpenApiSchema { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -199,12 +199,12 @@ public void ParseBasicSchemaWithExampleShouldSucceed() Type = JsonSchemaType.Object, Properties = { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -245,18 +245,18 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() { Schemas = { - ["ErrorModel"] = new() + ["ErrorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Minimum = 100, Maximum = 600 }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -267,7 +267,7 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() "code" } }, - ["ExtendedErrorModel"] = new() + ["ExtendedErrorModel"] = new OpenApiSchema() { AllOf = { @@ -278,7 +278,7 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() Required = {"rootCause"}, Properties = { - ["rootCause"] = new() + ["rootCause"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -302,7 +302,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() { Schemas = { - ["Pet"] = new() + ["Pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Discriminator = new() @@ -311,11 +311,11 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() }, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["petType"] = new() + ["petType"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -326,7 +326,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() "petType" } }, - ["Cat"] = new() + ["Cat"] = new OpenApiSchema() { Description = "A representation of a cat", AllOf = @@ -338,7 +338,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() Required = {"huntingSkill"}, Properties = { - ["huntingSkill"] = new() + ["huntingSkill"] = new OpenApiSchema() { Type = JsonSchemaType.String, Description = "The measured skill for hunting", @@ -354,7 +354,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() } } }, - ["Dog"] = new() + ["Dog"] = new OpenApiSchema() { Description = "A representation of a dog", AllOf = @@ -366,7 +366,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() Required = {"packSize"}, Properties = { - ["packSize"] = new() + ["packSize"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32", diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs index c84788ba8..5600610de 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs @@ -34,7 +34,7 @@ public class OpenApiCallbackTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -74,7 +74,7 @@ public class OpenApiCallbackTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs index 45448aa60..45c3dc1fc 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs @@ -16,17 +16,17 @@ public class OpenApiComponentsTests { public static OpenApiComponents AdvancedComponents = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 @@ -65,24 +65,24 @@ public class OpenApiComponentsTests public static OpenApiComponents AdvancedComponentsWithReference = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, ["property3"] = new OpenApiSchemaReference("schema2", null) } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -132,22 +132,22 @@ public class OpenApiComponentsTests public static OpenApiComponents BrokenComponents = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.String }, ["schema2"] = null, ["schema3"] = null, - ["schema4"] = new() + ["schema4"] = new OpenApiSchema() { Type = JsonSchemaType.String, - AllOf = new List + AllOf = new List { null, null, - new() + new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -163,12 +163,12 @@ public class OpenApiComponentsTests Schemas = { ["schema1"] = new OpenApiSchemaReference("schema2", null), - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -181,23 +181,23 @@ public class OpenApiComponentsTests { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -216,11 +216,11 @@ public class OpenApiComponentsTests public static OpenApiComponents ComponentsWithPathItem = new OpenApiComponents { - Schemas = new Dictionary() + Schemas = new Dictionary() { ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["property2"] = new OpenApiSchema() { @@ -230,9 +230,9 @@ public class OpenApiComponentsTests } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["property2"] = new OpenApiSchema() { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 5c905f238..3716a0b32 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -34,12 +34,12 @@ public OpenApiDocumentTests() Schemas = { ["schema1"] = new OpenApiSchemaReference("schema2", null), - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String, Annotations = new Dictionary { { "key1", "value" } } @@ -53,30 +53,25 @@ public OpenApiDocumentTests() { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String, Annotations = new Dictionary { { "key1", "value" } } } }, Annotations = new Dictionary { { "key1", "value" } }, - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schema1" - } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -90,13 +85,8 @@ public OpenApiDocumentTests() { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schema1" - } } } }; @@ -133,9 +123,9 @@ public OpenApiDocumentTests() public static readonly OpenApiComponents AdvancedComponentsWithReference = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet"] = new() + ["pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -143,48 +133,48 @@ public OpenApiDocumentTests() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -192,14 +182,14 @@ public OpenApiDocumentTests() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -208,12 +198,12 @@ public OpenApiDocumentTests() } }; - public static OpenApiSchema PetSchemaWithReference = AdvancedComponentsWithReference.Schemas["pet"]; + public static OpenApiSchema PetSchemaWithReference = AdvancedComponentsWithReference.Schemas["pet"] as OpenApiSchema; - public static OpenApiSchema NewPetSchemaWithReference = AdvancedComponentsWithReference.Schemas["newPet"]; + public static OpenApiSchema NewPetSchemaWithReference = AdvancedComponentsWithReference.Schemas["newPet"] as OpenApiSchema; public static OpenApiSchema ErrorModelSchemaWithReference = - AdvancedComponentsWithReference.Schemas["errorModel"]; + AdvancedComponentsWithReference.Schemas["errorModel"] as OpenApiSchema; public static readonly OpenApiDocument AdvancedDocumentWithReference = new OpenApiDocument { @@ -261,10 +251,10 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -276,7 +266,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -292,7 +282,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchemaWithReference @@ -300,7 +290,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchemaWithReference @@ -404,7 +394,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -464,7 +454,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -510,9 +500,9 @@ public OpenApiDocumentTests() public static readonly OpenApiComponents AdvancedComponents = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet"] = new() + ["pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -520,48 +510,48 @@ public OpenApiDocumentTests() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -569,14 +559,14 @@ public OpenApiDocumentTests() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -585,11 +575,11 @@ public OpenApiDocumentTests() } }; - public static readonly OpenApiSchema PetSchema = AdvancedComponents.Schemas["pet"]; + public static readonly OpenApiSchema PetSchema = AdvancedComponents.Schemas["pet"] as OpenApiSchema; - public static readonly OpenApiSchema NewPetSchema = AdvancedComponents.Schemas["newPet"]; + public static readonly OpenApiSchema NewPetSchema = AdvancedComponents.Schemas["newPet"] as OpenApiSchema; - public static readonly OpenApiSchema ErrorModelSchema = AdvancedComponents.Schemas["errorModel"]; + public static readonly OpenApiSchema ErrorModelSchema = AdvancedComponents.Schemas["errorModel"] as OpenApiSchema; public OpenApiDocument AdvancedDocument = new OpenApiDocument { @@ -637,10 +627,10 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -652,7 +642,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -668,7 +658,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -676,7 +666,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -780,7 +770,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -840,7 +830,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -923,7 +913,7 @@ public OpenApiDocumentTests() }, Components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { ["Pet"] = new OpenApiSchema() { @@ -931,18 +921,18 @@ public OpenApiDocumentTests() { "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -984,7 +974,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "The first operand", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Extensions = new Dictionary @@ -1003,7 +993,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "The second operand", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Extensions = new Dictionary @@ -1026,7 +1016,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1096,10 +1086,10 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -1111,7 +1101,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -1127,7 +1117,7 @@ public OpenApiDocumentTests() { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1135,7 +1125,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1239,7 +1229,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1299,7 +1289,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1561,14 +1551,6 @@ public async Task SerializeDocumentWithReferenceButNoComponents() { ["application/json"] = new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Id = "test", - Type = ReferenceType.Schema - } - } } } } @@ -1578,6 +1560,7 @@ public async Task SerializeDocumentWithReferenceButNoComponents() } } }; + document.Paths["/"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema = new OpenApiSchemaReference("test", document); // Act var actual = await document.SerializeAsync(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json); @@ -1738,7 +1721,7 @@ public async Task SerializeV2DocumentWithNonArraySchemaTypeDoesNotWriteOutCollec new OpenApiParameter { In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -1806,10 +1789,10 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() { Name = "id", In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -1825,7 +1808,7 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs index e368c587b..f6d4343cb 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs @@ -18,7 +18,7 @@ public class OpenApiHeaderTests public static OpenApiHeader AdvancedHeader = new() { Description = "sampleHeader", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -30,7 +30,7 @@ public class OpenApiHeaderTests public static OpenApiHeader ReferencedHeader = new() { Description = "sampleHeader", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs index df6b069ed..499477616 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs @@ -47,7 +47,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -64,7 +64,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -79,7 +79,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -135,7 +135,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -152,7 +152,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -167,7 +167,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -213,7 +213,7 @@ public class OpenApiOperationTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -225,16 +225,16 @@ public class OpenApiOperationTests { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -248,16 +248,16 @@ public class OpenApiOperationTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs index edec7bbd8..944920fab 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -40,14 +41,14 @@ public class OpenApiParameterTests Deprecated = false, Style = ParameterStyle.Simple, Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Title = "title2", Description = "description2", - OneOf = new List + OneOf = new List { - new() { Type = JsonSchemaType.Number, Format = "double" }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double" }, + new OpenApiSchema() { Type = JsonSchemaType.String } } }, Examples = @@ -67,10 +68,10 @@ public class OpenApiParameterTests Description = "description1", Style = ParameterStyle.Form, Explode = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Enum = { @@ -88,10 +89,10 @@ public class OpenApiParameterTests Description = "description1", Style = ParameterStyle.Form, Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Enum = [ @@ -106,7 +107,7 @@ public class OpenApiParameterTests { Name = "id", In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, AdditionalProperties = new OpenApiSchema @@ -116,35 +117,6 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter AdvancedHeaderParameterWithSchemaReference = new OpenApiParameter - { - Name = "name1", - In = ParameterLocation.Header, - Description = "description1", - Required = true, - Deprecated = false, - - Style = ParameterStyle.Simple, - Explode = true, - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schemaObject1" - }, - UnresolvedReference = true - }, - Examples = - { - ["test"] = new OpenApiExample() - { - Summary = "summary3", - Description = "description3" - } - } - }; - public static OpenApiParameter AdvancedHeaderParameterWithSchemaTypeObject = new() { Name = "name1", @@ -155,7 +127,7 @@ public class OpenApiParameterTests Style = ParameterStyle.Simple, Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object }, diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs index f391ef4d8..31d876b11 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs @@ -23,7 +23,7 @@ public class OpenApiRequestBodyTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -40,7 +40,7 @@ public class OpenApiRequestBodyTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs index f0991a1cb..374d43772 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs @@ -29,7 +29,7 @@ public class OpenApiResponseTests { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -46,7 +46,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -54,7 +54,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -68,7 +68,7 @@ public class OpenApiResponseTests { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -85,7 +85,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -93,7 +93,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -109,7 +109,7 @@ public class OpenApiResponseTests { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -121,7 +121,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -129,7 +129,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -145,7 +145,7 @@ public class OpenApiResponseTests { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -157,7 +157,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -165,7 +165,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -173,13 +173,6 @@ public class OpenApiResponseTests } }; - private readonly ITestOutputHelper _output; - - public OpenApiResponseTests(ITestOutputHelper output) - { - _output = output; - } - [Theory] [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json)] [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)] diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 5edd1c0d0..ffb10aa38 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -12,6 +12,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -45,38 +46,38 @@ public class OpenApiSchemaTests public static readonly OpenApiSchema AdvancedSchemaObject = new() { Title = "title1", - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 } }, }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property5"] = new() + ["property5"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property6"] = new() + ["property6"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property7"] = new() + ["property7"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 @@ -94,40 +95,40 @@ public class OpenApiSchemaTests public static readonly OpenApiSchema AdvancedSchemaWithAllOf = new() { Title = "title1", - AllOf = new List + AllOf = new List { - new() + new OpenApiSchema() { Title = "title2", - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 } }, }, - new() + new OpenApiSchema() { Title = "title3", - Properties = new Dictionary + Properties = new Dictionary { - ["property3"] = new() + ["property3"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property4"] = new() + ["property4"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property5"] = new() + ["property5"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 @@ -164,18 +165,18 @@ public class OpenApiSchemaTests { Title = "title1", Required = new HashSet { "property1" }, - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Required = new HashSet { "property3" }, - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15, @@ -184,21 +185,21 @@ public class OpenApiSchemaTests }, ReadOnly = true, }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property5"] = new() + ["property5"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property6"] = new() + ["property6"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property7"] = new() + ["property7"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 @@ -423,14 +424,14 @@ public async Task SerializeAsV2ShouldSetFormatPropertyInParentSchemaIfPresentInC // Arrange var schema = new OpenApiSchema { - OneOf = new List + OneOf = new List { - new() + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "decimal" }, - new() { Type = JsonSchemaType.String }, + new OpenApiSchema() { Type = JsonSchemaType.String }, } }; @@ -634,7 +635,7 @@ internal class SchemaVisitor : OpenApiVisitorBase { public List Titles = new(); - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { Titles.Add(schema.Title); } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs index 4f8e24f6e..ef9bea785 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs @@ -109,13 +109,15 @@ public void RequestBodyReferenceResolutionWorks() // Assert var localContent = _localRequestBodyReference.Content.Values.FirstOrDefault(); Assert.NotNull(localContent); - Assert.Equal("UserSchema", localContent.Schema.Reference.Id); + var localContentSchema = Assert.IsType(localContent.Schema); + Assert.Equal("UserSchema", localContentSchema.Reference.Id); Assert.Equal("User request body", _localRequestBodyReference.Description); Assert.Equal("application/json", _localRequestBodyReference.Content.First().Key); var externalContent = _externalRequestBodyReference.Content.Values.FirstOrDefault(); Assert.NotNull(externalContent); - Assert.Equal("UserSchema", externalContent.Schema.Reference.Id); + var externalContentSchema = Assert.IsType(externalContent.Schema); + Assert.Equal("UserSchema", externalContentSchema.Reference.Id); Assert.Equal("External Reference: User request body", _externalRequestBodyReference.Description); Assert.Equal("User creation request body", _openApiDoc_2.Components.RequestBodies.First().Value.Description); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs index 196759540..785ea5e55 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs @@ -92,12 +92,14 @@ public void ResponseReferenceResolutionWorks() // Assert var localContent = _localResponseReference.Content.FirstOrDefault(); Assert.Equal("text/plain", localContent.Key); - Assert.Equal("Pong", localContent.Value.Schema.Reference.Id); + var localContentSchema = Assert.IsType(localContent.Value.Schema); + Assert.Equal("Pong", localContentSchema.Reference.Id); Assert.Equal("OK response", _localResponseReference.Description); var externalContent = _externalResponseReference.Content.FirstOrDefault(); Assert.Equal("text/plain", externalContent.Key); - Assert.Equal("Pong", externalContent.Value.Schema.Reference.Id); + var externalContentSchema = Assert.IsType(externalContent.Value.Schema); + Assert.Equal("Pong", externalContentSchema.Reference.Id); Assert.Equal("External reference: OK response", _externalResponseReference.Description); Assert.Equal("OK", _openApiDoc_2.Components.Responses.First().Value.Description); diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index e5c9f7bb1..9d505dbce 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -360,7 +360,7 @@ namespace Microsoft.OpenApi.Models.Interfaces System.Collections.Generic.IDictionary Examples { get; } bool Explode { get; } bool Required { get; } - Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } Microsoft.OpenApi.Models.ParameterStyle? Style { get; } } public interface IOpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement @@ -383,7 +383,7 @@ namespace Microsoft.OpenApi.Models.Interfaces Microsoft.OpenApi.Models.ParameterLocation? In { get; } string Name { get; } bool Required { get; } - Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } Microsoft.OpenApi.Models.ParameterStyle? Style { get; } } public interface IOpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement @@ -405,6 +405,60 @@ namespace Microsoft.OpenApi.Models.Interfaces System.Collections.Generic.IDictionary Headers { get; } System.Collections.Generic.IDictionary Links { get; } } + public interface IOpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; } + bool AdditionalPropertiesAllowed { get; } + System.Collections.Generic.IList AllOf { get; } + System.Collections.Generic.IDictionary Annotations { get; } + System.Collections.Generic.IList AnyOf { get; } + string Comment { get; } + string Const { get; } + System.Text.Json.Nodes.JsonNode Default { get; } + System.Collections.Generic.IDictionary Definitions { get; } + bool Deprecated { get; } + Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; } + string DynamicAnchor { get; } + string DynamicRef { get; } + System.Collections.Generic.IList Enum { get; } + System.Text.Json.Nodes.JsonNode Example { get; } + System.Collections.Generic.IList Examples { get; } + bool? ExclusiveMaximum { get; } + bool? ExclusiveMinimum { get; } + Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + string Format { get; } + string Id { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; } + int? MaxItems { get; } + int? MaxLength { get; } + int? MaxProperties { get; } + decimal? Maximum { get; } + int? MinItems { get; } + int? MinLength { get; } + int? MinProperties { get; } + decimal? Minimum { get; } + decimal? MultipleOf { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; } + bool Nullable { get; } + System.Collections.Generic.IList OneOf { get; } + string Pattern { get; } + System.Collections.Generic.IDictionary PatternProperties { get; } + System.Collections.Generic.IDictionary Properties { get; } + bool ReadOnly { get; } + System.Collections.Generic.ISet Required { get; } + string Schema { get; } + string Title { get; } + Microsoft.OpenApi.Models.JsonSchemaType? Type { get; } + bool UnEvaluatedProperties { get; } + bool UnevaluatedProperties { get; } + bool? UniqueItems { get; } + System.Collections.Generic.IDictionary UnrecognizedKeywords { get; } + decimal? V31ExclusiveMaximum { get; } + decimal? V31ExclusiveMinimum { get; } + System.Collections.Generic.IDictionary Vocabulary { get; } + bool WriteOnly { get; } + Microsoft.OpenApi.Models.OpenApiXml Xml { get; } + } public interface IOpenApiSummarizedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement { string Summary { get; set; } @@ -447,7 +501,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary? PathItems { get; set; } public System.Collections.Generic.IDictionary? RequestBodies { get; set; } public System.Collections.Generic.IDictionary? Responses { get; set; } - public System.Collections.Generic.IDictionary? Schemas { get; set; } + public System.Collections.Generic.IDictionary? Schemas { get; set; } public System.Collections.Generic.IDictionary? SecuritySchemes { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -732,7 +786,7 @@ namespace Microsoft.OpenApi.Models public bool Explode { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } public bool Required { get; set; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; set; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -789,7 +843,7 @@ namespace Microsoft.OpenApi.Models public System.Text.Json.Nodes.JsonNode? Example { get; set; } public System.Collections.Generic.IDictionary? Examples { get; set; } public System.Collections.Generic.IDictionary? Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema? Schema { get; set; } + public virtual Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema? Schema { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -859,7 +913,7 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } public string Name { get; set; } public bool Required { get; set; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; set; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -936,68 +990,66 @@ namespace Microsoft.OpenApi.Models public OpenApiResponses() { } public OpenApiResponses(Microsoft.OpenApi.Models.OpenApiResponses openApiResponses) { } } - public class OpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiAnnotatable, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema { public OpenApiSchema() { } - public OpenApiSchema(Microsoft.OpenApi.Models.OpenApiSchema schema) { } + public OpenApiSchema(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; set; } + public bool AdditionalPropertiesAllowed { get; set; } + public System.Collections.Generic.IList AllOf { get; set; } public System.Collections.Generic.IDictionary Annotations { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema AdditionalProperties { get; set; } - public virtual bool AdditionalPropertiesAllowed { get; set; } - public virtual System.Collections.Generic.IList AllOf { get; set; } - public virtual System.Collections.Generic.IList AnyOf { get; set; } - public virtual string Comment { get; set; } - public virtual string Const { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Default { get; set; } - public virtual System.Collections.Generic.IDictionary Definitions { get; set; } - public virtual bool Deprecated { get; set; } - public virtual string Description { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } - public virtual string DynamicAnchor { get; set; } - public virtual string DynamicRef { get; set; } - public virtual System.Collections.Generic.IList Enum { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Example { get; set; } - public virtual System.Collections.Generic.IList Examples { get; set; } - public virtual bool? ExclusiveMaximum { get; set; } - public virtual bool? ExclusiveMinimum { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public virtual string Format { get; set; } - public virtual string Id { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Items { get; set; } - public virtual int? MaxItems { get; set; } - public virtual int? MaxLength { get; set; } - public virtual int? MaxProperties { get; set; } - public virtual decimal? Maximum { get; set; } - public virtual int? MinItems { get; set; } - public virtual int? MinLength { get; set; } - public virtual int? MinProperties { get; set; } - public virtual decimal? Minimum { get; set; } - public virtual decimal? MultipleOf { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Not { get; set; } - public virtual bool Nullable { get; set; } - public virtual System.Collections.Generic.IList OneOf { get; set; } - public virtual string Pattern { get; set; } - public virtual System.Collections.Generic.IDictionary PatternProperties { get; set; } - public virtual System.Collections.Generic.IDictionary Properties { get; set; } - public virtual bool ReadOnly { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual System.Collections.Generic.ISet Required { get; set; } - public virtual string Schema { get; set; } - public virtual string Title { get; set; } - public virtual Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } - public virtual bool UnEvaluatedProperties { get; set; } - public virtual bool UnevaluatedProperties { get; set; } - public virtual bool? UniqueItems { get; set; } - public virtual System.Collections.Generic.IDictionary UnrecognizedKeywords { get; set; } - public virtual bool UnresolvedReference { get; set; } - public virtual decimal? V31ExclusiveMaximum { get; set; } - public virtual decimal? V31ExclusiveMinimum { get; set; } - public virtual System.Collections.Generic.IDictionary Vocabulary { get; set; } - public virtual bool WriteOnly { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public System.Collections.Generic.IList AnyOf { get; set; } + public string Comment { get; set; } + public string Const { get; set; } + public System.Text.Json.Nodes.JsonNode Default { get; set; } + public System.Collections.Generic.IDictionary Definitions { get; set; } + public bool Deprecated { get; set; } + public string Description { get; set; } + public Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } + public string DynamicAnchor { get; set; } + public string DynamicRef { get; set; } + public System.Collections.Generic.IList Enum { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; set; } + public System.Collections.Generic.IList Examples { get; set; } + public bool? ExclusiveMaximum { get; set; } + public bool? ExclusiveMinimum { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } + public string Format { get; set; } + public string Id { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; set; } + public int? MaxItems { get; set; } + public int? MaxLength { get; set; } + public int? MaxProperties { get; set; } + public decimal? Maximum { get; set; } + public int? MinItems { get; set; } + public int? MinLength { get; set; } + public int? MinProperties { get; set; } + public decimal? Minimum { get; set; } + public decimal? MultipleOf { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; set; } + public bool Nullable { get; set; } + public System.Collections.Generic.IList OneOf { get; set; } + public string Pattern { get; set; } + public System.Collections.Generic.IDictionary PatternProperties { get; set; } + public System.Collections.Generic.IDictionary Properties { get; set; } + public bool ReadOnly { get; set; } + public System.Collections.Generic.ISet Required { get; set; } + public string Schema { get; set; } + public string Title { get; set; } + public Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } + public bool UnEvaluatedProperties { get; set; } + public bool UnevaluatedProperties { get; set; } + public bool? UniqueItems { get; set; } + public System.Collections.Generic.IDictionary UnrecognizedKeywords { get; set; } + public decimal? V31ExclusiveMaximum { get; set; } + public decimal? V31ExclusiveMinimum { get; set; } + public System.Collections.Generic.IDictionary Vocabulary { get; set; } + public bool WriteOnly { get; set; } + public Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -1181,8 +1233,8 @@ namespace Microsoft.OpenApi.Models.References public bool UnresolvedReference { get; set; } public abstract V CopyReferenceAsTargetElementWithOverrides(V source); public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiCallbackReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback { @@ -1219,7 +1271,7 @@ namespace Microsoft.OpenApi.Models.References public bool Explode { get; } public System.Collections.Generic.IDictionary Extensions { get; } public bool Required { get; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader source) { } } @@ -1253,7 +1305,7 @@ namespace Microsoft.OpenApi.Models.References public Microsoft.OpenApi.Models.ParameterLocation? In { get; } public string Name { get; } public bool Required { get; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter source) { } } @@ -1291,61 +1343,63 @@ namespace Microsoft.OpenApi.Models.References public System.Collections.Generic.IDictionary Links { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse source) { } } - public class OpenApiSchemaReference : Microsoft.OpenApi.Models.OpenApiSchema, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSchemaReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema { public OpenApiSchemaReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiSchema? Target { get; } - public override Microsoft.OpenApi.Models.OpenApiSchema AdditionalProperties { get; set; } - public override bool AdditionalPropertiesAllowed { get; set; } - public override System.Collections.Generic.IList AllOf { get; set; } - public override System.Collections.Generic.IList AnyOf { get; set; } - public override string Comment { get; set; } - public override string Const { get; set; } - public override System.Text.Json.Nodes.JsonNode Default { get; set; } - public override System.Collections.Generic.IDictionary Definitions { get; set; } - public override bool Deprecated { get; set; } - public override string Description { get; set; } - public override Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } - public override string DynamicAnchor { get; set; } - public override string DynamicRef { get; set; } - public override System.Collections.Generic.IList Enum { get; set; } - public override System.Text.Json.Nodes.JsonNode Example { get; set; } - public override System.Collections.Generic.IList Examples { get; set; } - public override bool? ExclusiveMaximum { get; set; } - public override bool? ExclusiveMinimum { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public override string Format { get; set; } - public override string Id { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Items { get; set; } - public override int? MaxItems { get; set; } - public override int? MaxLength { get; set; } - public override int? MaxProperties { get; set; } - public override decimal? Maximum { get; set; } - public override int? MinItems { get; set; } - public override int? MinLength { get; set; } - public override int? MinProperties { get; set; } - public override decimal? Minimum { get; set; } - public override decimal? MultipleOf { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Not { get; set; } - public override bool Nullable { get; set; } - public override System.Collections.Generic.IList OneOf { get; set; } - public override string Pattern { get; set; } - public override System.Collections.Generic.IDictionary PatternProperties { get; set; } - public override System.Collections.Generic.IDictionary Properties { get; set; } - public override bool ReadOnly { get; set; } - public override System.Collections.Generic.ISet Required { get; set; } - public override string Schema { get; set; } - public override string Title { get; set; } - public override Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } - public override bool UnEvaluatedProperties { get; set; } - public override bool UnevaluatedProperties { get; set; } - public override bool? UniqueItems { get; set; } - public override decimal? V31ExclusiveMaximum { get; set; } - public override decimal? V31ExclusiveMinimum { get; set; } - public override System.Collections.Generic.IDictionary Vocabulary { get; set; } - public override bool WriteOnly { get; set; } - public override Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; } + public bool AdditionalPropertiesAllowed { get; } + public System.Collections.Generic.IList AllOf { get; } + public System.Collections.Generic.IDictionary Annotations { get; } + public System.Collections.Generic.IList AnyOf { get; } + public string Comment { get; } + public string Const { get; } + public System.Text.Json.Nodes.JsonNode Default { get; } + public System.Collections.Generic.IDictionary Definitions { get; } + public bool Deprecated { get; } + public string Description { get; set; } + public Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; } + public string DynamicAnchor { get; } + public string DynamicRef { get; } + public System.Collections.Generic.IList Enum { get; } + public System.Text.Json.Nodes.JsonNode Example { get; } + public System.Collections.Generic.IList Examples { get; } + public bool? ExclusiveMaximum { get; } + public bool? ExclusiveMinimum { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + public string Format { get; } + public string Id { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; } + public int? MaxItems { get; } + public int? MaxLength { get; } + public int? MaxProperties { get; } + public decimal? Maximum { get; } + public int? MinItems { get; } + public int? MinLength { get; } + public int? MinProperties { get; } + public decimal? Minimum { get; } + public decimal? MultipleOf { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; } + public bool Nullable { get; } + public System.Collections.Generic.IList OneOf { get; } + public string Pattern { get; } + public System.Collections.Generic.IDictionary PatternProperties { get; } + public System.Collections.Generic.IDictionary Properties { get; } + public bool ReadOnly { get; } + public System.Collections.Generic.ISet Required { get; } + public string Schema { get; } + public string Title { get; } + public Microsoft.OpenApi.Models.JsonSchemaType? Type { get; } + public bool UnEvaluatedProperties { get; } + public bool UnevaluatedProperties { get; } + public bool? UniqueItems { get; } + public System.Collections.Generic.IDictionary UnrecognizedKeywords { get; } + public decimal? V31ExclusiveMaximum { get; } + public decimal? V31ExclusiveMinimum { get; } + public System.Collections.Generic.IDictionary Vocabulary { get; } + public bool WriteOnly { get; } + public Microsoft.OpenApi.Models.OpenApiXml Xml { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema source) { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -1567,6 +1621,7 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } @@ -1579,7 +1634,6 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiServer server) { } @@ -1666,6 +1720,7 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } @@ -1678,7 +1733,6 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiServer server) { } @@ -1784,7 +1838,7 @@ namespace Microsoft.OpenApi.Validations.Rules public static Microsoft.OpenApi.Validations.ValidationRule HeaderMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule MediaTypeMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule ParameterMismatchedDataType { get; } - public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; } + public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiOAuthFlowRules @@ -1823,9 +1877,9 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiSchemaRules { - public static Microsoft.OpenApi.Validations.ValidationRule ValidateSchemaDiscriminator { get; } - public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList childSchema) { } - public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.Models.OpenApiSchema schema, string discriminatorName) { } + public static Microsoft.OpenApi.Validations.ValidationRule ValidateSchemaDiscriminator { get; } + public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList childSchema) { } + public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema, string discriminatorName) { } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiServerRules diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs index 96afcb301..05b4bb62c 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs @@ -20,7 +20,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() var mediaType = new OpenApiMediaType { Example = 55, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -47,10 +47,10 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() var mediaType = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer, } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs index 13328046e..721445e23 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs @@ -71,7 +71,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() In = ParameterLocation.Path, Required = true, Example = 55, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -99,10 +99,10 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer, } @@ -159,7 +159,7 @@ public void PathParameterNotInThePathShouldReturnAnError() Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -194,7 +194,7 @@ public void PathParameterInThePathShouldBeOk() Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs index de9d58443..ea9a9660a 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs @@ -6,6 +6,8 @@ using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Validations; using Xunit; @@ -21,17 +23,12 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() var sharedSchema = new OpenApiSchema { Type = JsonSchemaType.String, - Reference = new() - { - Id = "test" - }, - UnresolvedReference = false }; var document = new OpenApiDocument(); document.Components = new() { - Schemas = new Dictionary() + Schemas = new Dictionary() { ["test"] = sharedSchema } @@ -53,7 +50,7 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() { ["application/json"] = new() { - Schema = sharedSchema + Schema = new OpenApiSchemaReference(sharedSchema, "test") } } } @@ -66,8 +63,8 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() // Act var rules = new Dictionary>() { - { typeof(OpenApiSchema), - new List() { new AlwaysFailRule() } + { typeof(IOpenApiSchema), + new List() { new AlwaysFailRule() } } }; @@ -75,7 +72,7 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() // Assert - Assert.True(errors.Count() == 1); + Assert.Single(errors); } [Fact] @@ -86,14 +83,10 @@ public void UnresolvedSchemaReferencedShouldNotBeValidated() var sharedSchema = new OpenApiSchema { Type = JsonSchemaType.String, - Reference = new() - { - Id = "test" - }, - UnresolvedReference = true }; var document = new OpenApiDocument(); + document.AddComponent("test", sharedSchema); document.Paths = new() { @@ -111,7 +104,7 @@ public void UnresolvedSchemaReferencedShouldNotBeValidated() { ["application/json"] = new() { - Schema = sharedSchema + Schema = new OpenApiSchemaReference(sharedSchema, "test") } } } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs index 9edd57c1e..d8820defc 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs @@ -7,6 +7,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; @@ -89,7 +90,7 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() }).Node }, Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -111,39 +112,38 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() { // Arrange - IEnumerable warnings; var schema = new OpenApiSchema { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } }, - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "password" }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -173,22 +173,18 @@ public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() // Act var defaultRuleSet = ValidationRuleSet.GetDefaultRuleSet(); - defaultRuleSet.Add(typeof(OpenApiSchema), OpenApiNonDefaultRules.SchemaMismatchedDataType); + defaultRuleSet.Add(typeof(IOpenApiSchema), OpenApiNonDefaultRules.SchemaMismatchedDataType); var validator = new OpenApiValidator(defaultRuleSet); var walker = new OpenApiWalker(validator); - walker.Walk(schema); - - warnings = validator.Warnings; - bool result = !warnings.Any(); + walker.Walk((IOpenApiSchema)schema); // Assert - Assert.False(result); + Assert.NotEmpty(validator.Warnings); } [Fact] public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator() { - IEnumerable errors; var components = new OpenApiComponents { Schemas = { @@ -198,7 +194,6 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD { Type = JsonSchemaType.Object, Discriminator = new() { PropertyName = "property1" }, - Reference = new() { Id = "schema1" } } } } @@ -208,17 +203,14 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD var walker = new OpenApiWalker(validator); walker.Walk(components); - errors = validator.Errors; - var result = !errors.Any(); - // Assert - Assert.False(result); + Assert.NotEmpty(validator.Errors); Assert.Equivalent(new List { new OpenApiValidatorError(nameof(OpenApiSchemaRules.ValidateSchemaDiscriminator),"#/schemas/schema1/discriminator", string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator, - "schema1", "property1")) - }, errors); + string.Empty, "property1")) + }, validator.Errors); } [Fact] @@ -238,9 +230,9 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim { PropertyName = "type" }, - OneOf = new List + OneOf = new List { - new() + new OpenApiSchema() { Properties = { @@ -252,14 +244,8 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim } } }, - Reference = new() - { - Type = ReferenceType.Schema, - Id = "Person" - } } }, - Reference = new() { Id = "Person" } } } } diff --git a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs index fbe0abf14..a11d64599 100644 --- a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs @@ -43,7 +43,7 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiComponents)); visitor.Visit(default(OpenApiExternalDocs)); - visitor.Visit(default(OpenApiSchema)); + visitor.Visit(default(IOpenApiSchema)); visitor.Visit(default(IDictionary)); visitor.Visit(default(IOpenApiLink)); visitor.Visit(default(IOpenApiCallback)); @@ -232,7 +232,7 @@ public override void Visit(OpenApiExternalDocs externalDocs) base.Visit(externalDocs); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { EncodeCall(); base.Visit(schema); diff --git a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs index c4ed91658..fa5b901dc 100644 --- a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs @@ -121,9 +121,9 @@ public void WalkDOMWithCycles() var loopySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["name"] = new() { Type = JsonSchemaType.String } + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }; @@ -133,7 +133,7 @@ public void WalkDOMWithCycles() { Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { ["loopy"] = loopySchema } @@ -161,22 +161,16 @@ public void WalkDOMWithCycles() [Fact] public void LocateReferences() { - var baseSchema = new OpenApiSchemaReference("base", null); + var baseSchema = new OpenApiSchema(); var derivedSchema = new OpenApiSchema { - AnyOf = new List { baseSchema }, - Reference = new() - { - Id = "derived", - Type = ReferenceType.Schema - }, - UnresolvedReference = false + AnyOf = new List { new OpenApiSchemaReference(baseSchema, "base") }, }; var testHeader = new OpenApiHeader() { - Schema = derivedSchema, + Schema = new OpenApiSchemaReference(derivedSchema, "derived"), }; var testHeaderReference = new OpenApiHeaderReference(testHeader, "test-header"); @@ -198,7 +192,7 @@ public void LocateReferences() { ["application/json"] = new() { - Schema = derivedSchema + Schema = new OpenApiSchemaReference(derivedSchema, "derived") } }, Headers = @@ -213,7 +207,7 @@ public void LocateReferences() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { ["derived"] = derivedSchema, ["base"] = baseSchema, @@ -305,7 +299,7 @@ public override void Visit(OpenApiMediaType mediaType) Locations.Add(this.PathString); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { Locations.Add(this.PathString); } diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs index 14e017fe9..38a9b2d8d 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Xunit; @@ -15,6 +16,11 @@ public class OpenApiWorkspaceTests [Fact] public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() { + var testSchema = new OpenApiSchema() + { + Type = JsonSchemaType.String, + Description = "The referenced one" + }; var doc = new OpenApiDocument() { Paths = new OpenApiPaths() @@ -33,14 +39,7 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() { ["application/json"] = new OpenApiMediaType() { - Schema = new() - { - Reference = new() - { - Id = "test", - Type = ReferenceType.Schema - } - } + Schema = new OpenApiSchemaReference(testSchema, "test") } } } @@ -56,11 +55,7 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() Components = new OpenApiComponents() { Schemas = { - ["test"] = new() - { - Type = JsonSchemaType.String, - Description = "The referenced one" - } + ["test"] = testSchema } } }; @@ -76,7 +71,8 @@ public void OpenApiWorkspacesCanResolveExternalReferences() var workspace = new OpenApiWorkspace(); var externalDoc = CreateCommonDocument(); - workspace.RegisterComponent("https://everything.json/common#/components/schemas/test", externalDoc.Components.Schemas["test"]); + var castSchema = Assert.IsType(externalDoc.Components.Schemas["test"]); + workspace.RegisterComponent("https://everything.json/common#/components/schemas/test", castSchema); var schema = workspace.ResolveReference("https://everything.json/common#/components/schemas/test"); @@ -135,7 +131,7 @@ private static OpenApiDocument CreateCommonDocument() { Schemas = { - ["test"] = new() + ["test"] = new OpenApiSchema() { Type = JsonSchemaType.String, Description = "The referenced one" diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index f10dba764..403922622 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -8,6 +8,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using Xunit; @@ -441,12 +442,6 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() var thingSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - UnresolvedReference = false, - Reference = new() - { - Id = "thing", - Type = ReferenceType.Schema - } }; var doc = new OpenApiDocument() @@ -470,7 +465,7 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() Content = { ["application/json"] = new() { - Schema = thingSchema + Schema = new OpenApiSchemaReference(thingSchema, "thing") } } } From 41759a1cb587d38392f730dfce74e974c76189c6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 28 Jan 2025 16:55:45 -0500 Subject: [PATCH 2/4] fix: missing doc comment for annotations Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs index 5495ab307..c0c78b765 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs @@ -299,6 +299,9 @@ public interface IOpenApiSchema : IOpenApiDescribedElement, IOpenApiSerializable /// public IDictionary UnrecognizedKeywords { get; } - /// + /// + /// Any annotation to attach to the schema to be used by the application. + /// Annotations are NOT (de)serialized with the schema and can be used for custom properties. + /// public IDictionary Annotations { get; } } From 4dfc9b8c533d454cefa3d576adb4d3d422747d16 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 28 Jan 2025 17:03:57 -0500 Subject: [PATCH 3/4] fix: removes virtual modifier in MediaType Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiMediaType.cs | 2 +- test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index d350c3251..6ae08b06a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -22,7 +22,7 @@ public class OpenApiMediaType : IOpenApiSerializable, IOpenApiExtensible /// /// The schema defining the type used for the request body. /// - public virtual IOpenApiSchema? Schema { get; set; } + public IOpenApiSchema? Schema { get; set; } /// /// Example of the media type. diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 9d505dbce..11020cee0 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -843,7 +843,7 @@ namespace Microsoft.OpenApi.Models public System.Text.Json.Nodes.JsonNode? Example { get; set; } public System.Collections.Generic.IDictionary? Examples { get; set; } public System.Collections.Generic.IDictionary? Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema? Schema { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema? Schema { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } From 21253f6d5e01500bd569e5b7f9d9b80c227b6088 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 28 Jan 2025 17:08:29 -0500 Subject: [PATCH 4/4] chore: reduce fluent assertion usage Signed-off-by: Vincent Biret --- .../V3Tests/OpenApiDocumentTests.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index d5ccec6cc..32c27b3b1 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -1390,12 +1390,8 @@ public async Task ParseDocumentWithEmptyPathsSucceeds() public async Task ParseDocumentWithExampleReferencesPasses() { // Act & Assert: Ensure no NullReferenceException is thrown - Func act = async () => - { - await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "docWithExampleReferences.yaml")); - }; - - await act.Should().NotThrowAsync(); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "docWithExampleReferences.yaml")); + Assert.Empty(result.Diagnostic.Errors); } } }