diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs
index 90d5c545b..8ed048427 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs
@@ -60,6 +60,66 @@ public static class OpenApiConstants
///
public const string Format = "format";
+ ///
+ /// Field: Schema
+ ///
+ public const string DollarSchema = "$schema";
+
+ ///
+ /// Field: Id
+ ///
+ public const string Id = "$id";
+
+ ///
+ /// Field: Comment
+ ///
+ public const string Comment = "$comment";
+
+ ///
+ /// Field: Vocabulary
+ ///
+ public const string Vocabulary = "$vocabulary";
+
+ ///
+ /// Field: DynamicRef
+ ///
+ public const string DynamicRef = "$dynamicRef";
+
+ ///
+ /// Field: DynamicAnchor
+ ///
+ public const string DynamicAnchor = "$dynamicAnchor";
+
+ ///
+ /// Field: RecursiveRef
+ ///
+ public const string RecursiveRef = "$recursiveRef";
+
+ ///
+ /// Field: RecursiveAnchor
+ ///
+ public const string RecursiveAnchor = "$recursiveAnchor";
+
+ ///
+ /// Field: Definitions
+ ///
+ public const string Defs = "$defs";
+
+ ///
+ /// Field: V31ExclusiveMaximum
+ ///
+ public const string V31ExclusiveMaximum = "exclusiveMaximum";
+
+ ///
+ /// Field: V31ExclusiveMinimum
+ ///
+ public const string V31ExclusiveMinimum = "exclusiveMinimum";
+
+ ///
+ /// Field: UnevaluatedProperties
+ ///
+ public const string UnevaluatedProperties = "unevaluatedProperties";
+
///
/// Field: Version
///
diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs
new file mode 100644
index 000000000..66fa00acd
--- /dev/null
+++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs
@@ -0,0 +1,795 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json.Nodes;
+using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
+using Microsoft.OpenApi.Writers;
+
+namespace Microsoft.OpenApi.Models
+{
+ ///
+ /// The Schema Object allows the definition of input and output data types.
+ ///
+ public class OpenApiSchema : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSerializable
+ {
+ ///
+ /// Follow JSON Schema definition. Short text providing information about the data.
+ ///
+ public string Title { get; set; }
+
+ ///
+ /// $schema, a JSON Schema dialect identifier. Value must be a URI
+ ///
+ public string Schema { get; set; }
+
+ ///
+ /// $id - Identifies a schema resource with its canonical URI.
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema.
+ ///
+ public string Comment { get; set; }
+
+ ///
+ /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema.
+ ///
+ public string Vocabulary { 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 string DynamicRef { 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 string DynamicAnchor { get; set; }
+
+ ///
+ /// $recursiveAnchor - used to construct recursive schemas i.e one that has a reference to its own root, identified by the empty fragment URI reference ("#")
+ ///
+ public string RecursiveAnchor { get; set; }
+
+ ///
+ /// $recursiveRef - used to construct recursive schemas i.e one that has a reference to its own root, identified by the empty fragment URI reference ("#")
+ ///
+ public string RecursiveRef { 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 IDictionary Definitions { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public decimal? V31ExclusiveMaximum { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public decimal? V31ExclusiveMinimum { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public bool UnEvaluatedProperties { 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 object Type { 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 string Format { 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 string Description { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public decimal? Maximum { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public bool? ExclusiveMaximum { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public decimal? Minimum { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public bool? ExclusiveMinimum { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public int? MaxLength { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public int? MinLength { 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 string Pattern { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public decimal? MultipleOf { 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 OpenApiAny Default { 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 bool ReadOnly { 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 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 IList AllOf { get; set; } = new List();
+
+ ///
+ /// 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; set; } = new List();
+
+ ///
+ /// 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; set; } = new List();
+
+ ///
+ /// 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 OpenApiSchema Not { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public ISet Required { get; set; } = new HashSet();
+
+ ///
+ /// 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 OpenApiSchema Items { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public int? MaxItems { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public int? MinItems { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public bool? UniqueItems { 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 IDictionary Properties { get; set; } = new Dictionary();
+
+ ///
+ /// 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; set; } = new Dictionary();
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public int? MaxProperties { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public int? MinProperties { get; set; }
+
+ ///
+ /// Indicates if the schema can contain properties other than those defined by the properties map.
+ ///
+ public bool AdditionalPropertiesAllowed { get; set; } = true;
+
+ ///
+ /// 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 OpenApiSchema AdditionalProperties { 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 OpenApiDiscriminator Discriminator { get; set; }
+
+ ///
+ /// 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 OpenApiAny Example { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public IList Enum { get; set; } = new List();
+
+ ///
+ /// Allows sending a null value for the defined schema. Default value is false.
+ ///
+ public bool Nullable { get; set; }
+
+ ///
+ /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+ ///
+ public bool UnevaluatedProperties { get; set;}
+
+ ///
+ /// Additional external documentation for this schema.
+ ///
+ public OpenApiExternalDocs ExternalDocs { get; set; }
+
+ ///
+ /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage.
+ /// Default value is false.
+ ///
+ public bool Deprecated { 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 OpenApiXml Xml { get; set; }
+
+ ///
+ /// This object MAY be extended with Specification Extensions.
+ ///
+ public IDictionary Extensions { get; set; } = new Dictionary();
+
+ ///
+ /// Indicates object is a placeholder reference to an actual object and does not contain valid data.
+ ///
+ public bool UnresolvedReference { get; set; }
+
+ ///
+ /// Reference object.
+ ///
+ public OpenApiReference Reference { get; set; }
+
+ ///
+ /// Parameterless constructor
+ ///
+ public OpenApiSchema() { }
+
+ ///
+ /// Initializes a copy of object
+ ///
+ public OpenApiSchema(OpenApiSchema schema)
+ {
+ Title = schema?.Title ?? Title;
+ Id = schema?.Id ?? Id;
+ Schema = schema?.Schema ?? Schema;
+ Comment = schema?.Comment ?? Comment;
+ Vocabulary = schema?.Vocabulary ?? Vocabulary;
+ DynamicAnchor = schema?.DynamicAnchor ?? DynamicAnchor;
+ DynamicRef = schema?.DynamicRef ?? DynamicRef;
+ RecursiveAnchor = schema?.RecursiveAnchor ?? RecursiveAnchor;
+ RecursiveRef = schema?.RecursiveRef ?? RecursiveRef;
+ Definitions = schema?.Definitions != null ? new Dictionary(schema.Definitions) : null;
+ UnevaluatedProperties = schema?.UnevaluatedProperties ?? UnevaluatedProperties;
+ V31ExclusiveMaximum = schema?.V31ExclusiveMaximum ?? V31ExclusiveMaximum;
+ V31ExclusiveMinimum = schema?.V31ExclusiveMinimum ?? V31ExclusiveMinimum;
+ Type = DeepCloneType(schema?.Type);
+ Format = schema?.Format ?? Format;
+ Description = schema?.Description ?? Description;
+ Maximum = schema?.Maximum ?? Maximum;
+ ExclusiveMaximum = schema?.ExclusiveMaximum ?? ExclusiveMaximum;
+ Minimum = schema?.Minimum ?? Minimum;
+ ExclusiveMinimum = schema?.ExclusiveMinimum ?? ExclusiveMinimum;
+ MaxLength = schema?.MaxLength ?? MaxLength;
+ MinLength = schema?.MinLength ?? MinLength;
+ Pattern = schema?.Pattern ?? Pattern;
+ MultipleOf = schema?.MultipleOf ?? MultipleOf;
+ Default = schema?.Default != null ? new(schema?.Default.Node) : 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;
+ Required = schema?.Required != null ? new HashSet(schema.Required) : null;
+ Items = schema?.Items != null ? new(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;
+ MaxProperties = schema?.MaxProperties ?? MaxProperties;
+ MinProperties = schema?.MinProperties ?? MinProperties;
+ AdditionalPropertiesAllowed = schema?.AdditionalPropertiesAllowed ?? AdditionalPropertiesAllowed;
+ AdditionalProperties = schema?.AdditionalProperties != null ? new(schema?.AdditionalProperties) : null;
+ Discriminator = schema?.Discriminator != null ? new(schema?.Discriminator) : null;
+ Example = schema?.Example != null ? new(schema?.Example.Node) : null;
+ Enum = schema?.Enum != null ? new List(schema.Enum) : null;
+ Nullable = schema?.Nullable ?? Nullable;
+ ExternalDocs = schema?.ExternalDocs != null ? new(schema?.ExternalDocs) : null;
+ 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;
+ }
+
+ ///
+ /// Serialize to Open Api v3.1
+ ///
+ public virtual void SerializeAsV31(IOpenApiWriter writer)
+ {
+ SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer),
+ (writer, element) => element.SerializeAsV31WithoutReference(writer));
+ }
+
+ ///
+ /// Serialize to Open Api v3.0
+ ///
+ public virtual void SerializeAsV3(IOpenApiWriter writer)
+ {
+ SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer),
+ (writer, element) => element.SerializeAsV3WithoutReference(writer));
+ }
+
+ private void SerializeInternal(IOpenApiWriter writer, Action callback,
+ Action action)
+ {
+ Utils.CheckArgumentNull(writer);
+ var target = this;
+ action(writer, target);
+ }
+
+ ///
+ /// Serialize to OpenAPI V3 document without using reference.
+ ///
+ public virtual void SerializeAsV31WithoutReference(IOpenApiWriter writer)
+ {
+ SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1,
+ (writer, element) => element.SerializeAsV31(writer));
+ }
+
+ ///
+ /// Serialize to OpenAPI V3 document without using reference.
+ ///
+ public virtual void SerializeAsV3WithoutReference(IOpenApiWriter writer)
+ {
+ SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0,
+ (writer, element) => element.SerializeAsV3(writer));
+ }
+
+///
+
+ public void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version,
+ Action callback)
+ {
+ writer.WriteStartObject();
+
+ if (version == OpenApiSpecVersion.OpenApi3_1)
+ {
+ WriteV31Properties(writer);
+ }
+
+ // title
+ writer.WriteProperty(OpenApiConstants.Title, Title);
+
+ // multipleOf
+ writer.WriteProperty(OpenApiConstants.MultipleOf, MultipleOf);
+
+ // maximum
+ writer.WriteProperty(OpenApiConstants.Maximum, Maximum);
+
+ // exclusiveMaximum
+ writer.WriteProperty(OpenApiConstants.ExclusiveMaximum, ExclusiveMaximum);
+
+ // minimum
+ writer.WriteProperty(OpenApiConstants.Minimum, Minimum);
+
+ // exclusiveMinimum
+ writer.WriteProperty(OpenApiConstants.ExclusiveMinimum, ExclusiveMinimum);
+
+ // maxLength
+ writer.WriteProperty(OpenApiConstants.MaxLength, MaxLength);
+
+ // minLength
+ writer.WriteProperty(OpenApiConstants.MinLength, MinLength);
+
+ // pattern
+ writer.WriteProperty(OpenApiConstants.Pattern, Pattern);
+
+ // maxItems
+ writer.WriteProperty(OpenApiConstants.MaxItems, MaxItems);
+
+ // minItems
+ writer.WriteProperty(OpenApiConstants.MinItems, MinItems);
+
+ // uniqueItems
+ writer.WriteProperty(OpenApiConstants.UniqueItems, UniqueItems);
+
+ // maxProperties
+ writer.WriteProperty(OpenApiConstants.MaxProperties, MaxProperties);
+
+ // minProperties
+ writer.WriteProperty(OpenApiConstants.MinProperties, MinProperties);
+
+ // required
+ writer.WriteOptionalCollection(OpenApiConstants.Required, Required, (w, s) => w.WriteValue(s));
+
+ // enum
+ writer.WriteOptionalCollection(OpenApiConstants.Enum, Enum, (nodeWriter, s) => nodeWriter.WriteAny(new OpenApiAny(s)));
+
+ // type
+ if (Type.GetType() == typeof(string))
+ {
+ writer.WriteProperty(OpenApiConstants.Type, (string)Type);
+ }
+ else
+ {
+ writer.WriteOptionalCollection(OpenApiConstants.Type, (string[])Type, (w, s) => w.WriteRaw(s));
+ }
+
+ // allOf
+ writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, (w, s) => s.SerializeAsV3(w));
+
+ // anyOf
+ writer.WriteOptionalCollection(OpenApiConstants.AnyOf, AnyOf, (w, s) => s.SerializeAsV3(w));
+
+ // oneOf
+ writer.WriteOptionalCollection(OpenApiConstants.OneOf, OneOf, (w, s) => s.SerializeAsV3(w));
+
+ // not
+ writer.WriteOptionalObject(OpenApiConstants.Not, Not, (w, s) => s.SerializeAsV3(w));
+
+ // items
+ writer.WriteOptionalObject(OpenApiConstants.Items, Items, (w, s) => s.SerializeAsV3(w));
+
+ // properties
+ writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, s) => s.SerializeAsV3(w));
+
+ // additionalProperties
+ if (AdditionalPropertiesAllowed)
+ {
+ writer.WriteOptionalObject(
+ OpenApiConstants.AdditionalProperties,
+ AdditionalProperties,
+ (w, s) => s.SerializeAsV3(w));
+ }
+ else
+ {
+ writer.WriteProperty(OpenApiConstants.AdditionalProperties, AdditionalPropertiesAllowed);
+ }
+
+ // description
+ writer.WriteProperty(OpenApiConstants.Description, Description);
+
+ // format
+ writer.WriteProperty(OpenApiConstants.Format, Format);
+
+ // default
+ writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
+
+ // nullable
+ writer.WriteProperty(OpenApiConstants.Nullable, Nullable, false);
+
+ // discriminator
+ writer.WriteOptionalObject(OpenApiConstants.Discriminator, Discriminator, (w, s) => s.SerializeAsV3(w));
+
+ // readOnly
+ writer.WriteProperty(OpenApiConstants.ReadOnly, ReadOnly, false);
+
+ // writeOnly
+ writer.WriteProperty(OpenApiConstants.WriteOnly, WriteOnly, false);
+
+ // xml
+ writer.WriteOptionalObject(OpenApiConstants.Xml, Xml, (w, s) => s.SerializeAsV2(w));
+
+ // externalDocs
+ writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, s) => s.SerializeAsV3(w));
+
+ // example
+ writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, e) => w.WriteAny(e));
+
+ // deprecated
+ writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false);
+
+ // extensions
+ writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0);
+
+ writer.WriteEndObject();
+ }
+
+///
+
+ public void SerializeAsV2WithoutReference(IOpenApiWriter writer)
+ {
+ SerializeAsV2WithoutReference(
+ writer: writer,
+ parentRequiredProperties: new HashSet(),
+ propertyName: null);
+ }
+
+///
+
+ public void SerializeAsV2(IOpenApiWriter writer)
+ {
+ SerializeAsV2(writer: writer, parentRequiredProperties: new HashSet(), propertyName: null);
+ }
+
+ internal void WriteV31Properties(IOpenApiWriter writer)
+ {
+ writer.WriteProperty(OpenApiConstants.Id, Id);
+ writer.WriteProperty(OpenApiConstants.DollarSchema, Schema);
+ writer.WriteProperty(OpenApiConstants.Comment, Comment);
+ writer.WriteProperty(OpenApiConstants.Vocabulary, Vocabulary);
+ writer.WriteOptionalMap(OpenApiConstants.Defs, Definitions, (w, s) => s.SerializeAsV3(w));
+ writer.WriteProperty(OpenApiConstants.DynamicRef, DynamicRef);
+ writer.WriteProperty(OpenApiConstants.DynamicAnchor, DynamicAnchor);
+ writer.WriteProperty(OpenApiConstants.RecursiveAnchor, RecursiveAnchor);
+ writer.WriteProperty(OpenApiConstants.RecursiveRef, RecursiveRef);
+ writer.WriteProperty(OpenApiConstants.V31ExclusiveMaximum, V31ExclusiveMaximum);
+ writer.WriteProperty(OpenApiConstants.V31ExclusiveMinimum, V31ExclusiveMinimum);
+ writer.WriteProperty(OpenApiConstants.UnevaluatedProperties, UnevaluatedProperties, false);
+ writer.WriteOptionalMap(OpenApiConstants.PatternProperties, PatternProperties, (w, s) => s.SerializeAsV31(w));
+ }
+
+ ///
+ /// Serialize to Open Api v2.0 and handles not marking the provided property
+ /// as readonly if its included in the provided list of required properties of parent schema.
+ ///
+ /// The open api writer.
+ /// The list of required properties in parent schema.
+ /// The property name that will be serialized.
+ internal void SerializeAsV2(
+ IOpenApiWriter writer,
+ ISet parentRequiredProperties,
+ string propertyName)
+ {
+ var target = this;
+ parentRequiredProperties ??= new HashSet();
+
+ target.SerializeAsV2WithoutReference(writer, parentRequiredProperties, propertyName);
+ }
+
+ ///
+ /// Serialize to OpenAPI V2 document without using reference and handles not marking the provided property
+ /// as readonly if its included in the provided list of required properties of parent schema.
+ ///
+ /// The open api writer.
+ /// The list of required properties in parent schema.
+ /// The property name that will be serialized.
+ internal void SerializeAsV2WithoutReference(
+ IOpenApiWriter writer,
+ ISet parentRequiredProperties,
+ string propertyName)
+ {
+ writer.WriteStartObject();
+ WriteAsSchemaProperties(writer, parentRequiredProperties, propertyName);
+ writer.WriteEndObject();
+ }
+
+ internal void WriteAsSchemaProperties(
+ IOpenApiWriter writer,
+ ISet parentRequiredProperties,
+ string propertyName)
+ {
+ // format
+ if (string.IsNullOrEmpty(Format))
+ {
+ Format = AllOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ??
+ AnyOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ??
+ OneOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format;
+ }
+
+ writer.WriteProperty(OpenApiConstants.Format, Format);
+
+ // title
+ writer.WriteProperty(OpenApiConstants.Title, Title);
+
+ // description
+ writer.WriteProperty(OpenApiConstants.Description, Description);
+
+ // default
+ writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
+
+ // multipleOf
+ writer.WriteProperty(OpenApiConstants.MultipleOf, MultipleOf);
+
+ // maximum
+ writer.WriteProperty(OpenApiConstants.Maximum, Maximum);
+
+ // exclusiveMaximum
+ writer.WriteProperty(OpenApiConstants.ExclusiveMaximum, ExclusiveMaximum);
+
+ // minimum
+ writer.WriteProperty(OpenApiConstants.Minimum, Minimum);
+
+ // exclusiveMinimum
+ writer.WriteProperty(OpenApiConstants.ExclusiveMinimum, ExclusiveMinimum);
+
+ // maxLength
+ writer.WriteProperty(OpenApiConstants.MaxLength, MaxLength);
+
+ // minLength
+ writer.WriteProperty(OpenApiConstants.MinLength, MinLength);
+
+ // pattern
+ writer.WriteProperty(OpenApiConstants.Pattern, Pattern);
+
+ // maxItems
+ writer.WriteProperty(OpenApiConstants.MaxItems, MaxItems);
+
+ // minItems
+ writer.WriteProperty(OpenApiConstants.MinItems, MinItems);
+
+ // uniqueItems
+ writer.WriteProperty(OpenApiConstants.UniqueItems, UniqueItems);
+
+ // maxProperties
+ writer.WriteProperty(OpenApiConstants.MaxProperties, MaxProperties);
+
+ // minProperties
+ writer.WriteProperty(OpenApiConstants.MinProperties, MinProperties);
+
+ // required
+ writer.WriteOptionalCollection(OpenApiConstants.Required, Required, (w, s) => w.WriteValue(s));
+
+ // enum
+ writer.WriteOptionalCollection(OpenApiConstants.Enum, Enum, (w, s) => w.WriteAny(new OpenApiAny(s)));
+
+ // type
+ writer.WriteProperty(OpenApiConstants.Type, (string)Type);
+
+ // items
+ writer.WriteOptionalObject(OpenApiConstants.Items, Items, (w, s) => s.SerializeAsV2(w));
+
+ // allOf
+ writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, (w, s) => s.SerializeAsV2(w));
+
+ // If there isn't already an allOf, and the schema contains a oneOf or anyOf write an allOf with the first
+ // schema in the list as an attempt to guess at a graceful downgrade situation.
+ if (AllOf == null || AllOf.Count == 0)
+ {
+ // anyOf (Not Supported in V2) - Write the first schema only as an allOf.
+ writer.WriteOptionalCollection(OpenApiConstants.AllOf, AnyOf?.Take(1), (w, s) => s.SerializeAsV2(w));
+
+ if (AnyOf == null || AnyOf.Count == 0)
+ {
+ // oneOf (Not Supported in V2) - Write the first schema only as an allOf.
+ writer.WriteOptionalCollection(OpenApiConstants.AllOf, OneOf?.Take(1), (w, s) => s.SerializeAsV2(w));
+ }
+ }
+
+ // properties
+ writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, key, s) =>
+ s.SerializeAsV2(w, Required, key));
+
+ // additionalProperties
+ if (AdditionalPropertiesAllowed)
+ {
+ writer.WriteOptionalObject(
+ OpenApiConstants.AdditionalProperties,
+ AdditionalProperties,
+ (w, s) => s.SerializeAsV2(w));
+ }
+ else
+ {
+ writer.WriteProperty(OpenApiConstants.AdditionalProperties, AdditionalPropertiesAllowed);
+ }
+
+ // discriminator
+ writer.WriteProperty(OpenApiConstants.Discriminator, Discriminator?.PropertyName);
+
+ // readOnly
+ // In V2 schema if a property is part of required properties of parent schema,
+ // it cannot be marked as readonly.
+ if (!parentRequiredProperties.Contains(propertyName))
+ {
+ writer.WriteProperty(name: OpenApiConstants.ReadOnly, value: ReadOnly, defaultValue: false);
+ }
+
+ // xml
+ writer.WriteOptionalObject(OpenApiConstants.Xml, Xml, (w, s) => s.SerializeAsV2(w));
+
+ // externalDocs
+ writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, s) => s.SerializeAsV2(w));
+
+ // example
+ writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, e) => w.WriteAny(e));
+
+ // extensions
+ writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi2_0);
+ }
+
+ private object DeepCloneType(object type)
+ {
+ if (type == null)
+ return null;
+
+ if (type is string)
+ {
+ return type; // Return the string as is
+ }
+
+ if (type is Array array)
+ {
+ Type elementType = type.GetType().GetElementType();
+ Array copiedArray = Array.CreateInstance(elementType, array.Length);
+ for (int i = 0; i < array?.Length; i++)
+ {
+ copiedArray.SetValue(DeepCloneType(array?.GetValue(i)), i);
+ }
+ return copiedArray;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/ParserHelper.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/ParserHelper.cs
index 9dd05ebdd..030572f68 100644
--- a/src/Microsoft.OpenApi/Reader/ParseNodes/ParserHelper.cs
+++ b/src/Microsoft.OpenApi/Reader/ParseNodes/ParserHelper.cs
@@ -4,7 +4,7 @@
using System;
using System.Globalization;
-namespace Microsoft.OpenApi.Readers.ParseNodes
+namespace Microsoft.OpenApi.Reader.ParseNodes
{
///
/// Useful tools to parse data
diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs
index 50b0321c7..54c584df2 100644
--- a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs
+++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs
@@ -212,7 +212,7 @@ public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hos
return LoadParameter(node, false, hostDocument);
}
- public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBody, OpenApiDocument hostDocument)
+ public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBody, OpenApiDocument hostDocument = null)
{
// Reset the local variables every time this method is called.
node.Context.SetTempStorage(TempStorageKeys.ParameterIsBodyOrFormData, false);
diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs
new file mode 100644
index 000000000..868ea2d32
--- /dev/null
+++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs
@@ -0,0 +1,178 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Reader.ParseNodes;
+
+namespace Microsoft.OpenApi.Reader.V2
+{
+ ///
+ /// Class containing logic to deserialize Open API V2 document into
+ /// runtime Open API object model.
+ ///
+ internal static partial class OpenApiV2Deserializer
+ {
+ private static readonly FixedFieldMap _openApiSchemaFixedFields = new()
+ {
+ {
+ "title",
+ (o, n, _) => o.Title = n.GetScalarValue()
+ },
+ {
+ "multipleOf",
+ (o, n, _) => o.MultipleOf = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
+ },
+ {
+ "maximum",
+ (o, n,_) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
+ },
+ {
+ "exclusiveMaximum",
+ (o, n, _) => o.ExclusiveMaximum = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "minimum",
+ (o, n, _) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
+ },
+ {
+ "exclusiveMinimum",
+ (o, n, _) => o.ExclusiveMinimum = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "maxLength",
+ (o, n, _) => o.MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minLength",
+ (o, n, _) => o.MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "pattern",
+ (o, n, _) => o.Pattern = n.GetScalarValue()
+ },
+ {
+ "maxItems",
+ (o, n, _) => o.MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minItems",
+ (o, n, _) => o.MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "uniqueItems",
+ (o, n, _) => o.UniqueItems = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "maxProperties",
+ (o, n, _) => o.MaxProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minProperties",
+ (o, n, _) => o.MinProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "required",
+ (o, n, _) => o.Required = new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))
+ },
+ {
+ "enum",
+ (o, n, _) => o.Enum = n.CreateListOfAny()
+ },
+
+ {
+ "type",
+ (o, n, _) => o.Type = n.GetScalarValue()
+ },
+ {
+ "allOf",
+ (o, n, t) => o.AllOf = n.CreateList(LoadOpenApiSchema, t)
+ },
+ {
+ "items",
+ (o, n, _) => o.Items = LoadOpenApiSchema(n)
+ },
+ {
+ "properties",
+ (o, n, t) => o.Properties = n.CreateMap(LoadOpenApiSchema, t)
+ },
+ {
+ "additionalProperties", (o, n, _) =>
+ {
+ if (n is ValueNode)
+ {
+ o.AdditionalPropertiesAllowed = bool.Parse(n.GetScalarValue());
+ }
+ else
+ {
+ o.AdditionalProperties = LoadOpenApiSchema(n);
+ }
+ }
+ },
+ {
+ "description",
+ (o, n, _) => o.Description = n.GetScalarValue()
+ },
+ {
+ "format",
+ (o, n, _) => o.Format = n.GetScalarValue()
+ },
+ {
+ "default",
+ (o, n, _) => o.Default = n.CreateAny()
+ },
+ {
+ "discriminator", (o, n, _) =>
+ {
+ o.Discriminator = new()
+ {
+ PropertyName = n.GetScalarValue()
+ };
+ }
+ },
+ {
+ "readOnly",
+ (o, n, _) => o.ReadOnly = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "xml",
+ (o, n, _) => o.Xml = LoadXml(n)
+ },
+ {
+ "externalDocs",
+ (o, n, _) => o.ExternalDocs = LoadExternalDocs(n)
+ },
+ {
+ "example",
+ (o, n, _) => o.Example = n.CreateAny()
+ },
+ };
+
+ private static readonly PatternFieldMap _openApiSchemaPatternFields = new PatternFieldMap
+ {
+ {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}
+ };
+
+ public static OpenApiSchema LoadOpenApiSchema(ParseNode node, OpenApiDocument hostDocument = null)
+ {
+ var mapNode = node.CheckMapNode("schema");
+
+ var pointer = mapNode.GetReferencePointer();
+ if (pointer != null)
+ {
+ return mapNode.GetReferencedObject(ReferenceType.Schema, pointer);
+ }
+
+ var schema = new OpenApiSchema();
+
+ foreach (var propertyNode in mapNode)
+ {
+ propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields);
+ }
+
+ return schema;
+ }
+ }
+}
diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs
new file mode 100644
index 000000000..51b427321
--- /dev/null
+++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs
@@ -0,0 +1,201 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Reader.ParseNodes;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace Microsoft.OpenApi.Reader.V3
+{
+ ///
+ /// Class containing logic to deserialize Open API V3 document into
+ /// runtime Open API object model.
+ ///
+ internal static partial class OpenApiV3Deserializer
+ {
+ private static readonly FixedFieldMap _openApiSchemaFixedFields = new()
+ {
+ {
+ "title",
+ (o, n, _) => o.Title = n.GetScalarValue()
+ },
+ {
+ "multipleOf",
+ (o, n, _) => o.MultipleOf = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
+ },
+ {
+ "maximum",
+ (o, n, _) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
+ },
+ {
+ "exclusiveMaximum",
+ (o, n, _) => o.ExclusiveMaximum = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "minimum",
+ (o, n, _) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
+ },
+ {
+ "exclusiveMinimum",
+ (o, n, _) => o.ExclusiveMinimum = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "maxLength",
+ (o, n, _) => o.MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minLength",
+ (o, n, _) => o.MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "pattern",
+ (o, n, _) => o.Pattern = n.GetScalarValue()
+ },
+ {
+ "maxItems",
+ (o, n, _) => o.MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minItems",
+ (o, n, _) => o.MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "uniqueItems",
+ (o, n, _) => o.UniqueItems = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "maxProperties",
+ (o, n, _) => o.MaxProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minProperties",
+ (o, n, _) => o.MinProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "required",
+ (o, n, _) => o.Required = new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))
+ },
+ {
+ "enum",
+ (o, n, _) => o.Enum = n.CreateListOfAny()
+ },
+ {
+ "type",
+ (o, n, _) => o.Type = n.GetScalarValue()
+ },
+ {
+ "allOf",
+ (o, n, t) => o.AllOf = n.CreateList(LoadOpenApiSchema, t)
+ },
+ {
+ "oneOf",
+ (o, n, _) => o.OneOf = n.CreateList(LoadOpenApiSchema)
+ },
+ {
+ "anyOf",
+ (o, n, t) => o.AnyOf = n.CreateList(LoadOpenApiSchema, t)
+ },
+ {
+ "not",
+ (o, n, _) => o.Not = LoadOpenApiSchema(n)
+ },
+ {
+ "items",
+ (o, n, _) => o.Items = LoadOpenApiSchema(n)
+ },
+ {
+ "properties",
+ (o, n, t) => o.Properties = n.CreateMap(LoadOpenApiSchema, t)
+ },
+ {
+ "additionalProperties", (o, n, _) =>
+ {
+ if (n is ValueNode)
+ {
+ o.AdditionalPropertiesAllowed = bool.Parse(n.GetScalarValue());
+ }
+ else
+ {
+ o.AdditionalProperties = LoadOpenApiSchema(n);
+ }
+ }
+ },
+ {
+ "description",
+ (o, n, _) => o.Description = n.GetScalarValue()
+ },
+ {
+ "format",
+ (o, n, _) => o.Format = n.GetScalarValue()
+ },
+ {
+ "default",
+ (o, n, _) => o.Default = n.CreateAny()
+ },
+ {
+ "nullable",
+ (o, n, _) => o.Nullable = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "discriminator",
+ (o, n, _) => o.Discriminator = LoadDiscriminator(n)
+ },
+ {
+ "readOnly",
+ (o, n, _) => o.ReadOnly = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "writeOnly",
+ (o, n, _) => o.WriteOnly = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "xml",
+ (o, n, _) => o.Xml = LoadXml(n)
+ },
+ {
+ "externalDocs",
+ (o, n, _) => o.ExternalDocs = LoadExternalDocs(n)
+ },
+ {
+ "example",
+ (o, n, _) => o.Example = n.CreateAny()
+ },
+ {
+ "deprecated",
+ (o, n, _) => o.Deprecated = bool.Parse(n.GetScalarValue())
+ },
+ };
+
+ private static readonly PatternFieldMap _openApiSchemaPatternFields = new()
+ {
+ {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}
+ };
+
+ public static OpenApiSchema LoadOpenApiSchema(ParseNode node, OpenApiDocument hostDocument = null)
+ {
+ var mapNode = node.CheckMapNode(OpenApiConstants.Schema);
+
+ var pointer = mapNode.GetReferencePointer();
+
+ if (pointer != null)
+ {
+ return new()
+ {
+ UnresolvedReference = true,
+ Reference = node.Context.VersionService.ConvertToOpenApiReference(pointer, ReferenceType.Schema)
+ };
+ }
+
+ var schema = new OpenApiSchema();
+
+ foreach (var propertyNode in mapNode)
+ {
+ propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields);
+ }
+
+ return schema;
+ }
+ }
+}
diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs
new file mode 100644
index 000000000..fa9d7dd93
--- /dev/null
+++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs
@@ -0,0 +1,246 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Reader.ParseNodes;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace Microsoft.OpenApi.Reader.V31
+{
+ internal static partial class OpenApiV31Deserializer
+ {
+ private static readonly FixedFieldMap _openApiSchemaFixedFields = new()
+ {
+ {
+ "title",
+ (o, n, _) => o.Title = n.GetScalarValue()
+ },
+ {
+ "$schema",
+ (o, n, _) => o.Schema = n.GetScalarValue()
+ },
+ {
+ "$id",
+ (o, n, _) => o.Id = n.GetScalarValue()
+ },
+ {
+ "$comment",
+ (o, n, _) => o.Comment = n.GetScalarValue()
+ },
+ {
+ "$vocabulary",
+ (o, n, _) => o.Vocabulary = n.GetScalarValue()
+ },
+ {
+ "$dynamicRef",
+ (o, n, _) => o.DynamicRef = n.GetScalarValue()
+ },
+ {
+ "$dynamicAnchor",
+ (o, n, _) => o.DynamicAnchor = n.GetScalarValue()
+ },
+ {
+ "$recursiveAnchor",
+ (o, n, _) => o.RecursiveAnchor = n.GetScalarValue()
+ },
+ {
+ "$recursiveRef",
+ (o, n, _) => o.RecursiveRef = n.GetScalarValue()
+ },
+ {
+ "$defs",
+ (o, n, t) => o.Definitions = n.CreateMap(LoadOpenApiSchema, t)
+ },
+ {
+ "multipleOf",
+ (o, n, _) => o.MultipleOf = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
+ },
+ {
+ "maximum",
+ (o, n, _) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
+ },
+ {
+ "exclusiveMaximum",
+ (o, n, _) => o.V31ExclusiveMaximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
+ },
+ {
+ "minimum",
+ (o, n, _) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
+ },
+ {
+ "exclusiveMinimum",
+ (o, n, _) => o.V31ExclusiveMinimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
+ },
+ {
+ "maxLength",
+ (o, n, _) => o.MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minLength",
+ (o, n, _) => o.MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "pattern",
+ (o, n, _) => o.Pattern = n.GetScalarValue()
+ },
+ {
+ "maxItems",
+ (o, n, _) => o.MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minItems",
+ (o, n, _) => o.MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "uniqueItems",
+ (o, n, _) => o.UniqueItems = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "unevaluatedProperties",
+ (o, n, _) => o.UnevaluatedProperties = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "maxProperties",
+ (o, n, _) => o.MaxProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "minProperties",
+ (o, n, _) => o.MinProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
+ },
+ {
+ "required",
+ (o, n, _) => o.Required = new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))
+ },
+ {
+ "enum",
+ (o, n, _) => o.Enum = n.CreateListOfAny()
+ },
+ {
+ "type",
+ (o, n, _) =>
+ {
+ o.Type = n is ValueNode
+ ? n.GetScalarValue()
+ : n.CreateSimpleList((n2, p) => n2.GetScalarValue()).ToArray();
+ }
+ },
+ {
+ "allOf",
+ (o, n, t) => o.AllOf = n.CreateList(LoadOpenApiSchema, t)
+ },
+ {
+ "oneOf",
+ (o, n, t) => o.OneOf = n.CreateList(LoadOpenApiSchema, t)
+ },
+ {
+ "anyOf",
+ (o, n, t) => o.AnyOf = n.CreateList(LoadOpenApiSchema, t)
+ },
+ {
+ "not",
+ (o, n, _) => o.Not = LoadOpenApiSchema(n)
+ },
+ {
+ "items",
+ (o, n, _) => o.Items = LoadOpenApiSchema(n)
+ },
+ {
+ "properties",
+ (o, n, t) => o.Properties = n.CreateMap(LoadOpenApiSchema, t)
+ },
+ {
+ "patternProperties",
+ (o, n, t) => o.PatternProperties = n.CreateMap(LoadOpenApiSchema, t)
+ },
+ {
+ "additionalProperties", (o, n, _) =>
+ {
+ if (n is ValueNode)
+ {
+ o.AdditionalPropertiesAllowed = bool.Parse(n.GetScalarValue());
+ }
+ else
+ {
+ o.AdditionalProperties = LoadOpenApiSchema(n);
+ }
+ }
+ },
+ {
+ "description",
+ (o, n, _) => o.Description = n.GetScalarValue()
+ },
+ {
+ "format",
+ (o, n, _) => o.Format = n.GetScalarValue()
+ },
+ {
+ "default",
+ (o, n, _) => o.Default = n.CreateAny()
+ },
+ {
+ "nullable",
+ (o, n, _) => o.Nullable = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "discriminator",
+ (o, n, _) => o.Discriminator = LoadDiscriminator(n)
+ },
+ {
+ "readOnly",
+ (o, n, _) => o.ReadOnly = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "writeOnly",
+ (o, n, _) => o.WriteOnly = bool.Parse(n.GetScalarValue())
+ },
+ {
+ "xml",
+ (o, n, _) => o.Xml = LoadXml(n)
+ },
+ {
+ "externalDocs",
+ (o, n, _) => o.ExternalDocs = LoadExternalDocs(n)
+ },
+ {
+ "example",
+ (o, n, _) => o.Example = n.CreateAny()
+ },
+ {
+ "deprecated",
+ (o, n, _) => o.Deprecated = bool.Parse(n.GetScalarValue())
+ },
+ };
+
+ private static readonly PatternFieldMap _openApiSchemaPatternFields = new()
+ {
+ {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}
+ };
+
+ public static OpenApiSchema LoadOpenApiSchema(ParseNode node, OpenApiDocument hostDocument = null)
+ {
+ var mapNode = node.CheckMapNode(OpenApiConstants.Schema);
+
+ var pointer = mapNode.GetReferencePointer();
+
+ if (pointer != null)
+ {
+ return new()
+ {
+ UnresolvedReference = true,
+ Reference = node.Context.VersionService.ConvertToOpenApiReference(pointer, ReferenceType.Schema)
+ };
+ }
+
+ var schema = new OpenApiSchema();
+
+ foreach (var propertyNode in mapNode)
+ {
+ propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields);
+ }
+
+ return schema;
+ }
+ }
+}
diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs
index 202e4e905..5e47f03b6 100644
--- a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs
+++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs
@@ -57,6 +57,7 @@ public OpenApiV31VersionService(OpenApiDiagnostic diagnostic)
[typeof(OpenApiResponse)] = OpenApiV31Deserializer.LoadResponse,
[typeof(OpenApiResponses)] = OpenApiV31Deserializer.LoadResponses,
[typeof(JsonSchema)] = OpenApiV31Deserializer.LoadSchema,
+ [typeof(OpenApiSchema)] = OpenApiV31Deserializer.LoadOpenApiSchema,
[typeof(OpenApiSecurityRequirement)] = OpenApiV31Deserializer.LoadSecurityRequirement,
[typeof(OpenApiSecurityScheme)] = OpenApiV31Deserializer.LoadSecurityScheme,
[typeof(OpenApiServer)] = OpenApiV31Deserializer.LoadServer,
diff --git a/test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs b/test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs
index 1368e103d..4e3500d6b 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs
@@ -2,7 +2,7 @@
// Licensed under the MIT license.
using System.Globalization;
-using Microsoft.OpenApi.Readers.ParseNodes;
+using Microsoft.OpenApi.Reader.ParseNodes;
using Xunit;
namespace Microsoft.OpenApi.Readers.Tests.ParseNodes
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs
new file mode 100644
index 000000000..72c5289e5
--- /dev/null
+++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs
@@ -0,0 +1,137 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.Collections.Generic;
+using System.IO;
+using FluentAssertions;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Reader;
+using Xunit;
+
+namespace Microsoft.OpenApi.Readers.Tests.V31Tests
+{
+ public class OpenApiSchemaTests
+ {
+ private const string SampleFolderPath = "V31Tests/Samples/OpenApiSchema/";
+
+ [Fact]
+ public void ParseBasicV31SchemaShouldSucceed()
+ {
+ var expectedObject = new OpenApiSchema()
+ {
+ Id = "https://example.com/arrays.schema.json",
+ Schema = "https://json-schema.org/draft/2020-12/schema",
+ Description = "A representation of a person, company, organization, or place",
+ Type = "object",
+ Properties = new Dictionary
+ {
+ ["fruits"] = new OpenApiSchema
+ {
+ Type = "array",
+ Items = new OpenApiSchema
+ {
+ Type = "string"
+ }
+ },
+ ["vegetables"] = new OpenApiSchema
+ {
+ Type = "array"
+ }
+ },
+ Definitions = new Dictionary
+ {
+ ["veggie"] = new OpenApiSchema
+ {
+ Type = "object",
+ Required = new HashSet
+ {
+ "veggieName",
+ "veggieLike"
+ },
+ Properties = new Dictionary
+ {
+ ["veggieName"] = new OpenApiSchema
+ {
+ Type = "string",
+ Description = "The name of the vegetable."
+ },
+ ["veggieLike"] = new OpenApiSchema
+ {
+ Type = "boolean",
+ Description = "Do I like this vegetable?"
+ }
+ }
+ }
+ }
+ };
+
+ // Act
+ var schema = OpenApiModelFactory.Load(
+ Path.Combine(SampleFolderPath, "jsonSchema.json"), OpenApiSpecVersion.OpenApi3_1, out _);
+
+ // Assert
+ schema.Should().BeEquivalentTo(expectedObject);
+ }
+
+ [Fact]
+ public void ParseSchemaWithTypeArrayWorks()
+ {
+ // Arrange
+ var schema = @"{
+ ""$id"": ""https://example.com/arrays.schema.json"",
+ ""$schema"": ""https://json-schema.org/draft/2020-12/schema"",
+ ""description"": ""A representation of a person, company, organization, or place"",
+ ""type"": [""object"", ""null""]
+}";
+
+ var expected = new OpenApiSchema()
+ {
+ Id = "https://example.com/arrays.schema.json",
+ Schema = "https://json-schema.org/draft/2020-12/schema",
+ Description = "A representation of a person, company, organization, or place",
+ Type = new string[] { "object", "null" }
+ };
+
+ // Act
+ var actual = OpenApiModelFactory.Parse(schema, OpenApiSpecVersion.OpenApi3_1, out _);
+
+ // Assert
+ actual.Should().BeEquivalentTo(expected);
+ }
+
+ [Fact]
+ public void TestSchemaCopyConstructorWithTypeArrayWorks()
+ {
+ /* Arrange
+ * Test schema's copy constructor for deep-cloning type array
+ */
+ var schemaWithTypeArray = new OpenApiSchema()
+ {
+ Type = new string[] { "array", "null" },
+ Items = new OpenApiSchema
+ {
+ Type = "string"
+ }
+ };
+
+ var simpleSchema = new OpenApiSchema()
+ {
+ Type = "string"
+ };
+
+ // Act
+ var schemaWithArrayCopy = new OpenApiSchema(schemaWithTypeArray);
+ schemaWithArrayCopy.Type = "string";
+
+ var simpleSchemaCopy = new OpenApiSchema(simpleSchema);
+ simpleSchemaCopy.Type = new string[] { "string", "null" };
+
+ // Assert
+ schemaWithArrayCopy.Type.Should().NotBeEquivalentTo(schemaWithTypeArray.Type);
+ schemaWithTypeArray.Type = new string[] { "string", "null" };
+
+ simpleSchemaCopy.Type.Should().NotBeEquivalentTo(simpleSchema.Type);
+ simpleSchema.Type = "string";
+ }
+ }
+}
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/jsonSchema.json b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/jsonSchema.json
new file mode 100644
index 000000000..84b1ea211
--- /dev/null
+++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/jsonSchema.json
@@ -0,0 +1,33 @@
+{
+ "$id": "https://example.com/arrays.schema.json",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "description": "A representation of a person, company, organization, or place",
+ "type": "object",
+ "properties": {
+ "fruits": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "vegetables": {
+ "type": "array"
+ }
+ },
+ "$defs": {
+ "veggie": {
+ "type": "object",
+ "required": [ "veggieName", "veggieLike" ],
+ "properties": {
+ "veggieName": {
+ "type": "string",
+ "description": "The name of the vegetable."
+ },
+ "veggieLike": {
+ "type": "boolean",
+ "description": "Do I like this vegetable?"
+ }
+ }
+ }
+ }
+}
diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs
new file mode 100644
index 000000000..b67f64de1
--- /dev/null
+++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs
@@ -0,0 +1,108 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.Collections.Generic;
+using Microsoft.OpenApi.Models;
+using Xunit;
+using FluentAssertions;
+using Microsoft.OpenApi.Extensions;
+
+namespace Microsoft.OpenApi.Tests.Models
+{
+ public class OpenApiSchemaTests
+ {
+ public static OpenApiSchema BasicV31Schema = new()
+ {
+ Id = "https://example.com/arrays.schema.json",
+ Schema = "https://json-schema.org/draft/2020-12/schema",
+ Description = "A representation of a person, company, organization, or place",
+ Type = "object",
+ Properties = new Dictionary
+ {
+ ["fruits"] = new OpenApiSchema
+ {
+ Type = "array",
+ Items = new OpenApiSchema
+ {
+ Type = "string"
+ }
+ },
+ ["vegetables"] = new OpenApiSchema
+ {
+ Type = "array"
+ }
+ },
+ Definitions = new Dictionary
+ {
+ ["veggie"] = new OpenApiSchema
+ {
+ Type = "object",
+ Required = new HashSet{ "veggieName", "veggieLike" },
+ Properties = new Dictionary
+ {
+ ["veggieName"] = new OpenApiSchema
+ {
+ Type = "string",
+ Description = "The name of the vegetable."
+ },
+ ["veggieLike"] = new OpenApiSchema
+ {
+ Type = "boolean",
+ Description = "Do I like this vegetable?"
+ }
+ }
+ }
+ }
+ };
+
+ [Fact]
+ public void SerializeBasicV31SchemaWorks()
+ {
+ // Arrange
+ var expected = @"{
+ ""$id"": ""https://example.com/arrays.schema.json"",
+ ""$schema"": ""https://json-schema.org/draft/2020-12/schema"",
+ ""$defs"": {
+ ""veggie"": {
+ ""required"": [
+ ""veggieName"",
+ ""veggieLike""
+ ],
+ ""type"": ""object"",
+ ""properties"": {
+ ""veggieName"": {
+ ""type"": ""string"",
+ ""description"": ""The name of the vegetable.""
+ },
+ ""veggieLike"": {
+ ""type"": ""boolean"",
+ ""description"": ""Do I like this vegetable?""
+ }
+ }
+ }
+ },
+ ""type"": ""object"",
+ ""properties"": {
+ ""fruits"": {
+ ""type"": ""array"",
+ ""items"": {
+ ""type"": ""string""
+ }
+ },
+ ""vegetables"": {
+ ""type"": ""array""
+ }
+ },
+ ""description"": ""A representation of a person, company, organization, or place""
+}";
+
+ // Act
+ var actual = BasicV31Schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_1);
+
+ // Assert
+ actual = actual.MakeLineBreaksEnvironmentNeutral();
+ expected = expected.MakeLineBreaksEnvironmentNeutral();
+ actual.Should().Be(expected);
+ }
+ }
+}
diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
index 7e0730600..58d7a576e 100755
--- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
+++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
@@ -459,6 +459,7 @@ namespace Microsoft.OpenApi.Models
public const string BodyName = "x-bodyName";
public const string Callbacks = "callbacks";
public const string ClientCredentials = "clientCredentials";
+ public const string Comment = "$comment";
public const string Components = "components";
public const string ComponentsSegment = "/components/";
public const string Consumes = "consumes";
@@ -471,11 +472,15 @@ namespace Microsoft.OpenApi.Models
public const string DefaultName = "Default Name";
public const string DefaultTitle = "Default Title";
public const string Definitions = "definitions";
+ public const string Defs = "$defs";
public const string Delete = "delete";
public const string Deprecated = "deprecated";
public const string Description = "description";
public const string Discriminator = "discriminator";
public const string DollarRef = "$ref";
+ public const string DollarSchema = "$schema";
+ public const string DynamicAnchor = "$dynamicAnchor";
+ public const string DynamicRef = "$dynamicRef";
public const string Email = "email";
public const string Encoding = "encoding";
public const string Enum = "enum";
@@ -495,6 +500,7 @@ namespace Microsoft.OpenApi.Models
public const string Head = "head";
public const string Headers = "headers";
public const string Host = "host";
+ public const string Id = "$id";
public const string Identifier = "identifier";
public const string Implicit = "implicit";
public const string In = "in";
@@ -539,6 +545,8 @@ namespace Microsoft.OpenApi.Models
public const string PropertyName = "propertyName";
public const string Put = "put";
public const string ReadOnly = "readOnly";
+ public const string RecursiveAnchor = "$recursiveAnchor";
+ public const string RecursiveRef = "$recursiveRef";
public const string RefreshUrl = "refreshUrl";
public const string RequestBodies = "requestBodies";
public const string RequestBody = "requestBody";
@@ -563,13 +571,17 @@ namespace Microsoft.OpenApi.Models
public const string TokenUrl = "tokenUrl";
public const string Trace = "trace";
public const string Type = "type";
+ public const string UnevaluatedProperties = "unevaluatedProperties";
public const string UniqueItems = "uniqueItems";
public const string Url = "url";
public const string V2ReferenceUri = "https://registry/definitions/";
+ public const string V31ExclusiveMaximum = "exclusiveMaximum";
+ public const string V31ExclusiveMinimum = "exclusiveMinimum";
public const string V3ReferenceUri = "https://registry/components/schemas/";
public const string Value = "value";
public const string Variables = "variables";
public const string Version = "version";
+ public const string Vocabulary = "$vocabulary";
public const string Webhooks = "webhooks";
public const string Wrapped = "wrapped";
public const string WriteOnly = "writeOnly";
@@ -945,6 +957,71 @@ namespace Microsoft.OpenApi.Models
public OpenApiResponses() { }
public OpenApiResponses(Microsoft.OpenApi.Models.OpenApiResponses openApiResponses) { }
}
+ public class OpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
+ {
+ public OpenApiSchema() { }
+ public OpenApiSchema(Microsoft.OpenApi.Models.OpenApiSchema schema) { }
+ public Microsoft.OpenApi.Models.OpenApiSchema AdditionalProperties { get; set; }
+ public bool AdditionalPropertiesAllowed { get; set; }
+ public System.Collections.Generic.IList AllOf { get; set; }
+ public System.Collections.Generic.IList AnyOf { get; set; }
+ public string Comment { get; set; }
+ public Microsoft.OpenApi.Any.OpenApiAny 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 Microsoft.OpenApi.Any.OpenApiAny Example { 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.OpenApiSchema 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.OpenApiSchema 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 string RecursiveAnchor { get; set; }
+ public string RecursiveRef { get; set; }
+ public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; }
+ public System.Collections.Generic.ISet Required { get; set; }
+ public string Schema { get; set; }
+ public string Title { get; set; }
+ public object Type { get; set; }
+ public bool UnEvaluatedProperties { get; set; }
+ public bool UnevaluatedProperties { get; set; }
+ public bool? UniqueItems { get; set; }
+ public bool UnresolvedReference { get; set; }
+ public decimal? V31ExclusiveMaximum { get; set; }
+ public decimal? V31ExclusiveMinimum { get; set; }
+ public string 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 SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
+ public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
+ public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
+ public virtual void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
+ public virtual void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
+ public void SerializeInternalWithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion version, System.Action callback) { }
+ }
public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
{
public OpenApiSecurityRequirement() { }