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
         /// </summary>
         public const string Format = "format";
 
+        /// <summary>
+        /// Field: Schema
+        /// </summary>
+        public const string DollarSchema = "$schema";
+
+        /// <summary>
+        /// Field: Id
+        /// </summary>
+        public const string Id = "$id";
+
+        /// <summary>
+        /// Field: Comment
+        /// </summary>
+        public const string Comment = "$comment";
+
+        /// <summary>
+        /// Field: Vocabulary
+        /// </summary>
+        public const string Vocabulary = "$vocabulary";
+
+        /// <summary>
+        /// Field: DynamicRef
+        /// </summary>
+        public const string DynamicRef = "$dynamicRef";
+
+        /// <summary>
+        /// Field: DynamicAnchor
+        /// </summary>
+        public const string DynamicAnchor = "$dynamicAnchor";
+
+        /// <summary>
+        /// Field: RecursiveRef
+        /// </summary>
+        public const string RecursiveRef = "$recursiveRef";
+
+        /// <summary>
+        /// Field: RecursiveAnchor
+        /// </summary>
+        public const string RecursiveAnchor = "$recursiveAnchor";
+
+        /// <summary>
+        /// Field: Definitions
+        /// </summary>
+        public const string Defs = "$defs";
+
+        /// <summary>
+        /// Field: V31ExclusiveMaximum
+        /// </summary>
+        public const string V31ExclusiveMaximum = "exclusiveMaximum";
+
+        /// <summary>
+        /// Field: V31ExclusiveMinimum
+        /// </summary>
+        public const string V31ExclusiveMinimum = "exclusiveMinimum";
+
+        /// <summary>
+        /// Field: UnevaluatedProperties
+        /// </summary>
+        public const string UnevaluatedProperties = "unevaluatedProperties";
+
         /// <summary>
         /// Field: Version
         /// </summary>
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
+{
+    /// <summary>
+    /// The Schema Object allows the definition of input and output data types.
+    /// </summary>
+    public class OpenApiSchema : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSerializable
+    {
+        /// <summary>
+        /// Follow JSON Schema definition. Short text providing information about the data.
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// $schema, a JSON Schema dialect identifier. Value must be a URI
+        /// </summary>
+        public string Schema { get; set; }
+
+        /// <summary>
+        /// $id - Identifies a schema resource with its canonical URI.
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema.
+        /// </summary>
+        public string Comment { get; set; }
+
+        /// <summary>
+        /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema.
+        /// </summary>
+        public string Vocabulary { get; set; }
+
+        /// <summary>
+        /// $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
+        /// </summary>
+        public string DynamicRef { get; set; }
+
+        /// <summary>
+        /// $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.
+        /// </summary>
+        public string DynamicAnchor { get; set; }
+
+        /// <summary>
+        /// $recursiveAnchor - used to construct recursive schemas i.e one that has a reference to its own root, identified by the empty fragment URI reference ("#")
+        /// </summary>
+        public string RecursiveAnchor { get; set; }
+
+        /// <summary>
+        /// $recursiveRef - used to construct recursive schemas i.e one that has a reference to its own root, identified by the empty fragment URI reference ("#")
+        /// </summary>
+        public string RecursiveRef { get; set; }
+
+        /// <summary>
+        /// $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
+        /// </summary>
+        public IDictionary<string, OpenApiSchema> Definitions { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public decimal? V31ExclusiveMaximum { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public decimal? V31ExclusiveMinimum { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public bool UnEvaluatedProperties { get; set; }     
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// Value MUST be a string in V2 and V3.
+        /// </summary>
+        public object Type { get; set; }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public string Format { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// CommonMark syntax MAY be used for rich text representation.
+        /// </summary>
+        public string Description { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public decimal? Maximum { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public bool? ExclusiveMaximum { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public decimal? Minimum { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public bool? ExclusiveMinimum { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public int? MaxLength { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public int? MinLength { get; set; }
+
+        /// <summary>
+        /// 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
+        /// </summary>
+        public string Pattern { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public decimal? MultipleOf { get; set; }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public OpenApiAny Default { get; set; }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public bool ReadOnly { get; set; }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public bool WriteOnly { get; set; }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public IList<OpenApiSchema> AllOf { get; set; } = new List<OpenApiSchema>();
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public IList<OpenApiSchema> OneOf { get; set; } = new List<OpenApiSchema>();
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public IList<OpenApiSchema> AnyOf { get; set; } = new List<OpenApiSchema>();
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public OpenApiSchema Not { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public ISet<string> Required { get; set; } = new HashSet<string>();
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public OpenApiSchema Items { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public int? MaxItems { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public int? MinItems { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public bool? UniqueItems { get; set; }
+
+        /// <summary>
+        /// 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).
+        /// </summary>
+        public IDictionary<string, OpenApiSchema> Properties { get; set; } = new Dictionary<string, OpenApiSchema>();
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public IDictionary<string, OpenApiSchema> PatternProperties { get; set; } = new Dictionary<string, OpenApiSchema>();
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public int? MaxProperties { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public int? MinProperties { get; set; }
+
+        /// <summary>
+        /// Indicates if the schema can contain properties other than those defined by the properties map.
+        /// </summary>
+        public bool AdditionalPropertiesAllowed { get; set; } = true;
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public OpenApiSchema AdditionalProperties { get; set; }
+
+        /// <summary>
+        /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate
+        /// between other schemas which may satisfy the payload description.
+        /// </summary>
+        public OpenApiDiscriminator Discriminator { get; set; }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public OpenApiAny Example { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public IList<JsonNode> Enum { get; set; } = new List<JsonNode>();
+
+        /// <summary>
+        /// Allows sending a null value for the defined schema. Default value is false.
+        /// </summary>
+        public bool Nullable { get; set; }
+
+        /// <summary>
+        /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
+        /// </summary>
+        public bool UnevaluatedProperties { get; set;}
+
+        /// <summary>
+        /// Additional external documentation for this schema.
+        /// </summary>
+        public OpenApiExternalDocs ExternalDocs { get; set; }
+
+        /// <summary>
+        /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage.
+        /// Default value is false.
+        /// </summary>
+        public bool Deprecated { get; set; }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public OpenApiXml Xml { get; set; }
+
+        /// <summary>
+        /// This object MAY be extended with Specification Extensions.
+        /// </summary>
+        public IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
+
+        /// <summary>
+        /// Indicates object is a placeholder reference to an actual object and does not contain valid data.
+        /// </summary>
+        public bool UnresolvedReference { get; set; }
+
+        /// <summary>
+        /// Reference object.
+        /// </summary>
+        public OpenApiReference Reference { get; set; }
+
+        /// <summary>
+        /// Parameterless constructor
+        /// </summary>
+        public OpenApiSchema() { }
+
+        /// <summary>
+        /// Initializes a copy of <see cref="OpenApiSchema"/> object
+        /// </summary>
+        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<string, OpenApiSchema>(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<OpenApiSchema>(schema.AllOf) : null;
+            OneOf = schema?.OneOf != null ? new List<OpenApiSchema>(schema.OneOf) : null;
+            AnyOf = schema?.AnyOf != null ? new List<OpenApiSchema>(schema.AnyOf) : null;
+            Not = schema?.Not != null ? new(schema?.Not) : null;
+            Required = schema?.Required != null ? new HashSet<string>(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<string, OpenApiSchema>(schema.Properties) : null;
+            PatternProperties = schema?.PatternProperties != null ? new Dictionary<string, OpenApiSchema>(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<JsonNode>(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<string, IOpenApiExtension>(schema.Extensions) : null;
+            UnresolvedReference = schema?.UnresolvedReference ?? UnresolvedReference;
+            Reference = schema?.Reference != null ? new(schema?.Reference) : null;
+        }
+
+        /// <summary>
+        /// Serialize <see cref="OpenApiParameter"/> to Open Api v3.1
+        /// </summary>
+        public virtual void SerializeAsV31(IOpenApiWriter writer)
+        {
+            SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer),
+                (writer, element) => element.SerializeAsV31WithoutReference(writer));
+        }
+
+        /// <summary>
+        /// Serialize <see cref="OpenApiParameter"/> to Open Api v3.0
+        /// </summary>
+        public virtual void SerializeAsV3(IOpenApiWriter writer)
+        {
+            SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer),
+                (writer, element) => element.SerializeAsV3WithoutReference(writer));
+        }
+
+        private void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, IOpenApiSerializable> callback,
+            Action<IOpenApiWriter, IOpenApiReferenceable> action)
+        {
+            Utils.CheckArgumentNull(writer);
+            var target = this;
+            action(writer, target);
+        }
+
+        /// <summary>
+        /// Serialize to OpenAPI V3 document without using reference.
+        /// </summary>
+        public virtual void SerializeAsV31WithoutReference(IOpenApiWriter writer)
+        {
+            SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1,
+                (writer, element) => element.SerializeAsV31(writer));
+        }
+
+        /// <summary>
+        /// Serialize to OpenAPI V3 document without using reference.
+        /// </summary>
+        public virtual void SerializeAsV3WithoutReference(IOpenApiWriter writer)
+        {
+            SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0,
+                (writer, element) => element.SerializeAsV3(writer));
+        }
+
+/// <inheritdoc/>
+
+        public void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version,
+            Action<IOpenApiWriter, IOpenApiSerializable> 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();
+        }
+
+/// <inheritdoc/>
+
+        public void SerializeAsV2WithoutReference(IOpenApiWriter writer)
+        {
+            SerializeAsV2WithoutReference(
+                            writer: writer,
+                            parentRequiredProperties: new HashSet<string>(),
+                            propertyName: null);
+        }
+
+/// <inheritdoc/>
+
+        public void SerializeAsV2(IOpenApiWriter writer)
+        {
+            SerializeAsV2(writer: writer, parentRequiredProperties: new HashSet<string>(), 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));
+        }
+
+        /// <summary>
+        /// Serialize <see cref="OpenApiSchema"/> 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.
+        /// </summary>
+        /// <param name="writer">The open api writer.</param>
+        /// <param name="parentRequiredProperties">The list of required properties in parent schema.</param>
+        /// <param name="propertyName">The property name that will be serialized.</param>
+        internal void SerializeAsV2(
+            IOpenApiWriter writer,
+            ISet<string> parentRequiredProperties,
+            string propertyName)
+        {
+            var target = this;
+            parentRequiredProperties ??= new HashSet<string>();
+
+            target.SerializeAsV2WithoutReference(writer, parentRequiredProperties, propertyName);
+        }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        /// <param name="writer">The open api writer.</param>
+        /// <param name="parentRequiredProperties">The list of required properties in parent schema.</param>
+        /// <param name="propertyName">The property name that will be serialized.</param>
+        internal void SerializeAsV2WithoutReference(
+            IOpenApiWriter writer,
+            ISet<string> parentRequiredProperties,
+            string propertyName)
+        {
+            writer.WriteStartObject();
+            WriteAsSchemaProperties(writer, parentRequiredProperties, propertyName);
+            writer.WriteEndObject();
+        }
+
+        internal void WriteAsSchemaProperties(
+            IOpenApiWriter writer,
+            ISet<string> 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
 {
     /// <summary>
     /// 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
+{
+    /// <summary>
+    /// Class containing logic to deserialize Open API V2 document into
+    /// runtime Open API object model.
+    /// </summary>
+    internal static partial class OpenApiV2Deserializer
+    {
+        private static readonly FixedFieldMap<OpenApiSchema> _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<string>(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<OpenApiSchema> _openApiSchemaPatternFields = new PatternFieldMap<OpenApiSchema>
+        {
+            {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<OpenApiSchema>(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
+{
+    /// <summary>
+    /// Class containing logic to deserialize Open API V3 document into
+    /// runtime Open API object model.
+    /// </summary>
+    internal static partial class OpenApiV3Deserializer
+    {
+        private static readonly FixedFieldMap<OpenApiSchema> _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<string>(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<OpenApiSchema> _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<OpenApiSchema> _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<string>(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<OpenApiSchema> _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<string, OpenApiSchema>
+                {
+                    ["fruits"] = new OpenApiSchema
+                    {
+                        Type = "array",
+                        Items = new OpenApiSchema
+                        {
+                            Type = "string"
+                        }
+                    },
+                    ["vegetables"] = new OpenApiSchema
+                    {
+                        Type = "array"
+                    }
+                },
+                Definitions = new Dictionary<string, OpenApiSchema>
+                {
+                    ["veggie"] = new OpenApiSchema
+                    {
+                        Type = "object",
+                        Required = new HashSet<string>
+                        {
+                            "veggieName",
+                            "veggieLike"
+                        },
+                        Properties = new Dictionary<string, OpenApiSchema>
+                        {
+                            ["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<OpenApiSchema>(
+                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<OpenApiSchema>(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<string, OpenApiSchema>
+            {
+                ["fruits"] = new OpenApiSchema
+                {
+                    Type = "array",
+                    Items = new OpenApiSchema
+                    {
+                        Type = "string"
+                    }
+                },
+                ["vegetables"] = new OpenApiSchema
+                {
+                    Type = "array"
+                }
+            },
+            Definitions = new Dictionary<string, OpenApiSchema>
+            {
+                ["veggie"] = new OpenApiSchema
+                {
+                    Type = "object",
+                    Required = new HashSet<string>{ "veggieName", "veggieLike" },
+                    Properties = new Dictionary<string, OpenApiSchema>
+                    {
+                        ["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<Microsoft.OpenApi.Models.OpenApiSchema> AllOf { get; set; }
+        public System.Collections.Generic.IList<Microsoft.OpenApi.Models.OpenApiSchema> AnyOf { get; set; }
+        public string Comment { get; set; }
+        public Microsoft.OpenApi.Any.OpenApiAny Default { get; set; }
+        public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.Models.OpenApiSchema> 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<System.Text.Json.Nodes.JsonNode> 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<string, Microsoft.OpenApi.Interfaces.IOpenApiExtension> 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<Microsoft.OpenApi.Models.OpenApiSchema> OneOf { get; set; }
+        public string Pattern { get; set; }
+        public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.Models.OpenApiSchema> PatternProperties { get; set; }
+        public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.Models.OpenApiSchema> 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<string> 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<Microsoft.OpenApi.Writers.IOpenApiWriter, Microsoft.OpenApi.Interfaces.IOpenApiSerializable> callback) { }
+    }
     public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary<Microsoft.OpenApi.Models.OpenApiSecurityScheme, System.Collections.Generic.IList<string>>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
     {
         public OpenApiSecurityRequirement() { }