diff --git a/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs b/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs
index faf03c3f0..ee57125dd 100644
--- a/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs
+++ b/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs
@@ -14,9 +14,9 @@ internal static class OpenApiExtensibleExtensions
         /// A  value matching the provided extensionKey. Return null when extensionKey is not found. 
         internal static string GetExtension(this IDictionary extensions, string extensionKey)
         {
-            if (extensions.TryGetValue(extensionKey, out var value) && value is OpenApiString castValue)
+            if (extensions.TryGetValue(extensionKey, out var value) && value is OpenApiAny castValue)
             {
-                return castValue.Value;
+                return castValue.Node.GetValue();
             }
             return string.Empty;
         }
diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs
index 96d3cc17d..c2bbc97d0 100644
--- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs
+++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs
@@ -52,7 +52,8 @@ public override void Visit(OpenApiSchema schema)
 
         public override void Visit(OpenApiPathItem pathItem)
         {
-            if (pathItem.Operations.TryGetValue(OperationType.Put, out var value))
+            if (pathItem.Operations.TryGetValue(OperationType.Put, out var value) &&
+                value.OperationId != null)
             {
                 var operationId = value.OperationId;
                 pathItem.Operations[OperationType.Put].OperationId = ResolvePutOperationId(operationId);
@@ -67,14 +68,14 @@ public override void Visit(OpenApiOperation operation)
                 throw new ArgumentException($"OperationId is required {PathString}", nameof(operation));
 
             var operationId = operation.OperationId;
-            var operationTypeExtension = operation.Extensions.GetExtension("x-ms-docs-operation-type");
+            var operationTypeExtension = operation.Extensions?.GetExtension("x-ms-docs-operation-type");
             if (operationTypeExtension.IsEquals("function"))
-                operation.Parameters = ResolveFunctionParameters(operation.Parameters);
+                operation.Parameters = ResolveFunctionParameters(operation.Parameters ?? new List());
 
             // Order matters. Resolve operationId.
             operationId = RemoveHashSuffix(operationId);
             if (operationTypeExtension.IsEquals("action") || operationTypeExtension.IsEquals("function"))
-                operationId = RemoveKeyTypeSegment(operationId, operation.Parameters);
+                operationId = RemoveKeyTypeSegment(operationId, operation.Parameters ?? new List());
             operationId = SingularizeAndDeduplicateOperationId(operationId.SplitByChar('.'));
             operationId = ResolveODataCastOperationId(operationId);
             operationId = ResolveByRefOperationId(operationId);
@@ -165,10 +166,10 @@ private static IList ResolveFunctionParameters(IList ResolveFunctionParameters(IList
+
 
   
     Exe
diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs
index d98508a13..c981639e9 100644
--- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs
+++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs
@@ -29,6 +29,7 @@
 using Microsoft.OpenApi.Hidi.Utilities;
 using Microsoft.OpenApi.Models;
 using Microsoft.OpenApi.OData;
+using Microsoft.OpenApi.Reader;
 using Microsoft.OpenApi.Readers;
 using Microsoft.OpenApi.Services;
 using Microsoft.OpenApi.Writers;
@@ -38,6 +39,12 @@ namespace Microsoft.OpenApi.Hidi
 {
     internal static class OpenApiService
     {
+        static OpenApiService()
+        {
+            OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader());
+            OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader());
+        }
+
         /// 
         /// Implementation of the transform command
         /// 
@@ -52,7 +59,12 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
             {
                 if (options.Output == null)
                 {
-                    var inputExtension = GetInputPathExtension(options.OpenApi, options.Csdl);
+#pragma warning disable CA1308 // Normalize strings to uppercase
+                    var extension = options.OpenApiFormat?.GetDisplayName().ToLowerInvariant();
+                    var inputExtension = !string.IsNullOrEmpty(extension) ? string.Concat(".", extension) 
+                        : GetInputPathExtension(options.OpenApi, options.Csdl);
+
+#pragma warning restore CA1308 // Normalize strings to uppercase
                     options.Output = new($"./output{inputExtension}");
                 };
 
@@ -67,7 +79,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
 
                 // Default to yaml and OpenApiVersion 3 during csdl to OpenApi conversion
                 var openApiFormat = options.OpenApiFormat ?? (!string.IsNullOrEmpty(options.OpenApi) ? GetOpenApiFormat(options.OpenApi, logger) : OpenApiFormat.Yaml);
-                var openApiVersion = options.Version != null ? TryParseOpenApiSpecVersion(options.Version) : OpenApiSpecVersion.OpenApi3_0;
+                var openApiVersion = options.Version != null ? TryParseOpenApiSpecVersion(options.Version) : OpenApiSpecVersion.OpenApi3_1;
 
                 // If ApiManifest is provided, set the referenced OpenAPI document
                 var apiDependency = await FindApiDependencyAsync(options.FilterOptions.FilterByApiManifest, logger, cancellationToken).ConfigureAwait(false);
@@ -85,7 +97,8 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
                 }
 
                 // Load OpenAPI document
-                var document = await GetOpenApiAsync(options, logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false);
+                var format = OpenApiModelFactory.GetFormat(options.OpenApi);
+                var document = await GetOpenApiAsync(options, format, logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false);
 
                 if (options.FilterOptions != null)
                 {
@@ -212,7 +225,7 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma
         }
 
         // Get OpenAPI document either from OpenAPI or CSDL
-        private static async Task GetOpenApiAsync(HidiOptions options, ILogger logger, string? metadataVersion = null, CancellationToken cancellationToken = default)
+        private static async Task GetOpenApiAsync(HidiOptions options, string format, ILogger logger, string? metadataVersion = null, CancellationToken cancellationToken = default)
         {
             OpenApiDocument document;
             Stream stream;
@@ -233,7 +246,7 @@ private static async Task GetOpenApiAsync(HidiOptions options,
                         await stream.DisposeAsync().ConfigureAwait(false);
                     }
 
-                    document = await ConvertCsdlToOpenApiAsync(filteredStream ?? stream, metadataVersion, options.SettingsConfig, cancellationToken).ConfigureAwait(false);
+                    document = await ConvertCsdlToOpenApiAsync(filteredStream ?? stream, format, metadataVersion, options.SettingsConfig, cancellationToken).ConfigureAwait(false);
                     stopwatch.Stop();
                     logger.LogTrace("{Timestamp}ms: Generated OpenAPI with {Paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count);
                 }
@@ -375,14 +388,16 @@ private static async Task ParseOpenApiAsync(string openApiFile, bool
             {
                 stopwatch.Start();
 
-                result = await new OpenApiStreamReader(new()
-                    {
+                var settings = new OpenApiReaderSettings
+                {
                     LoadExternalRefs = inlineExternal,
                     BaseUrl = openApiFile.StartsWith("http", StringComparison.OrdinalIgnoreCase) ?
                         new(openApiFile) :
                         new Uri("file://" + new FileInfo(openApiFile).DirectoryName + Path.DirectorySeparatorChar)
-                }
-                ).ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+                };
+
+                var format = OpenApiModelFactory.GetFormat(openApiFile);
+                result = await OpenApiDocument.LoadAsync(stream, format, settings, cancellationToken).ConfigureAwait(false);
 
                 logger.LogTrace("{Timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds);
 
@@ -398,7 +413,7 @@ private static async Task ParseOpenApiAsync(string openApiFile, bool
         /// 
         /// The CSDL stream.
         /// An OpenAPI document.
-        public static async Task ConvertCsdlToOpenApiAsync(Stream csdl, string? metadataVersion = null, IConfiguration? settings = null, CancellationToken token = default)
+        public static async Task ConvertCsdlToOpenApiAsync(Stream csdl, string format, string? metadataVersion = null, IConfiguration? settings = null, CancellationToken token = default)
         {
             using var reader = new StreamReader(csdl);
             var csdlText = await reader.ReadToEndAsync(token).ConfigureAwait(false);
@@ -406,7 +421,7 @@ public static async Task ConvertCsdlToOpenApiAsync(Stream csdl,
             settings ??= SettingsUtilities.GetConfiguration();
 
             var document = edmModel.ConvertToOpenApi(SettingsUtilities.GetOpenApiConvertSettings(settings, metadataVersion));
-            document = FixReferences(document);
+            document = FixReferences(document, format);
 
             return document;
         }
@@ -416,14 +431,15 @@ public static async Task ConvertCsdlToOpenApiAsync(Stream csdl,
         /// 
         ///  The converted OpenApiDocument.
         ///  A valid OpenApiDocument instance.
-        public static OpenApiDocument FixReferences(OpenApiDocument document)
+        public static OpenApiDocument FixReferences(OpenApiDocument document, string format)
         {
             // This method is only needed because the output of ConvertToOpenApi isn't quite a valid OpenApiDocument instance.
             // So we write it out, and read it back in again to fix it up.
 
             var sb = new StringBuilder();
             document.SerializeAsV3(new OpenApiYamlWriter(new StringWriter(sb)));
-            var doc = new OpenApiStringReader().Read(sb.ToString(), out _);
+
+            var doc = OpenApiDocument.Parse(sb.ToString(), format).OpenApiDocument;
 
             return doc;
         }
@@ -571,7 +587,8 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl
                     throw new ArgumentException("Please input a file path or URL");
                 }
 
-                var document = await GetOpenApiAsync(options, logger, null, cancellationToken).ConfigureAwait(false);
+                var format = OpenApiModelFactory.GetFormat(options.OpenApi);
+                var document = await GetOpenApiAsync(options, format, logger, null, cancellationToken).ConfigureAwait(false);
 
                 using (logger.BeginScope("Creating diagram"))
                 {
@@ -732,7 +749,8 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg
             }
 
             // Load OpenAPI document
-            var document = await GetOpenApiAsync(options, logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false);
+            var format = OpenApiModelFactory.GetFormat(options.OpenApi);
+            var document = await GetOpenApiAsync(options, format, logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false);
 
             cancellationToken.ThrowIfCancellationRequested();
 
@@ -750,7 +768,7 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg
             // Write OpenAPI to Output folder
             options.Output = new(Path.Combine(options.OutputFolder, "openapi.json"));
             options.TerseOutput = true;
-            WriteOpenApi(options, OpenApiFormat.Json, OpenApiSpecVersion.OpenApi3_0, document, logger);
+            WriteOpenApi(options, OpenApiFormat.Json, OpenApiSpecVersion.OpenApi3_1, document, logger);
 
             // Create OpenAIPluginManifest from ApiDependency and OpenAPI document
             var manifest = new OpenAIPluginManifest
diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiSpecVersionHelper.cs b/src/Microsoft.OpenApi.Hidi/OpenApiSpecVersionHelper.cs
index 234298481..222f7a8c6 100644
--- a/src/Microsoft.OpenApi.Hidi/OpenApiSpecVersionHelper.cs
+++ b/src/Microsoft.OpenApi.Hidi/OpenApiSpecVersionHelper.cs
@@ -2,7 +2,6 @@
 // Licensed under the MIT license.
 
 using System;
-using System.Linq;
 
 namespace Microsoft.OpenApi.Hidi
 {
@@ -14,17 +13,30 @@ public static OpenApiSpecVersion TryParseOpenApiSpecVersion(string value)
             {
                 throw new InvalidOperationException("Please provide a version");
             }
-            var res = value.Split('.', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
+            // Split the version string by the dot
+            var versionSegments = value.Split('.', StringSplitOptions.RemoveEmptyEntries);
 
-            if (int.TryParse(res, out var result))
+            if (!int.TryParse(versionSegments[0], out var majorVersion)
+                || !int.TryParse(versionSegments[1], out var minorVersion))
             {
-                if (result is >= 2 and < 3)
-                {
-                    return OpenApiSpecVersion.OpenApi2_0;
-                }
+                throw new InvalidOperationException("Invalid version format. Please provide a valid OpenAPI version (e.g., 2.0, 3.0, 3.1).");
             }
 
-            return OpenApiSpecVersion.OpenApi3_0; // default
+            // Check for specific version matches
+            if (majorVersion == 2)
+            {
+                return OpenApiSpecVersion.OpenApi2_0;
+            }
+            else if (majorVersion == 3 && minorVersion == 0)
+            {
+                return OpenApiSpecVersion.OpenApi3_0;
+            }
+            else if (majorVersion == 3 && minorVersion == 1)
+            {
+                return OpenApiSpecVersion.OpenApi3_1;
+            }
+
+            return OpenApiSpecVersion.OpenApi3_1; // default
         }
     }
 }
diff --git a/src/Microsoft.OpenApi.Hidi/Program.cs b/src/Microsoft.OpenApi.Hidi/Program.cs
index d5846dca9..ddbb96fe9 100644
--- a/src/Microsoft.OpenApi.Hidi/Program.cs
+++ b/src/Microsoft.OpenApi.Hidi/Program.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
 using System.CommandLine;
diff --git a/src/Microsoft.OpenApi.Readers/Interface/IOpenApiReader.cs b/src/Microsoft.OpenApi.Readers/Interface/IOpenApiReader.cs
deleted file mode 100644
index 8991c9b59..000000000
--- a/src/Microsoft.OpenApi.Readers/Interface/IOpenApiReader.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Models;
-
-namespace Microsoft.OpenApi.Readers.Interface
-{
-    /// 
-    /// Interface for Open API readers.
-    /// 
-    /// The type of input to read from.
-    /// The type of diagnostic for information from reading process.
-    public interface IOpenApiReader where TDiagnostic : IDiagnostic
-    {
-        /// 
-        /// Reads the input and parses it into an Open API document.
-        /// 
-        /// The input to read from.
-        /// The diagnostic entity containing information from the reading process.
-        /// The Open API document.
-        OpenApiDocument Read(TInput input, out TDiagnostic diagnostic);
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
index ca868b9b6..68204d9c9 100644
--- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
+++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
@@ -1,9 +1,9 @@
-
+
     
         netstandard2.0
         latest
         true
-        1.6.22
+        2.0.0-preview1
         OpenAPI.NET Readers for JSON and YAML documents
         true
         
@@ -17,6 +17,12 @@
         ..\Microsoft.OpenApi.snk
     
 
+    
+      
+      
+      
+    
+
     
 
         
@@ -25,6 +31,7 @@
         
 
         
+        
     
 
     
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
deleted file mode 100644
index c6c8add2f..000000000
--- a/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using System.IO;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.OpenApi.Interfaces;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.Interface;
-
-namespace Microsoft.OpenApi.Readers
-{
-    /// 
-    /// Service class for converting streams into OpenApiDocument instances
-    /// 
-    public class OpenApiStreamReader : IOpenApiReader
-    {
-        private readonly OpenApiReaderSettings _settings;
-
-        /// 
-        /// Create stream reader with custom settings if desired.
-        /// 
-        /// 
-        public OpenApiStreamReader(OpenApiReaderSettings settings = null)
-        {
-            _settings = settings ?? new OpenApiReaderSettings();
-
-            if((_settings.ReferenceResolution == ReferenceResolutionSetting.ResolveAllReferences || _settings.LoadExternalRefs)
-                && _settings.BaseUrl == null)
-            {
-                throw new ArgumentException("BaseUrl must be provided to resolve external references.");
-            }
-        }
-
-        /// 
-        /// Reads the stream input and parses it into an Open API document.
-        /// 
-        /// Stream containing OpenAPI description to parse.
-        /// Returns diagnostic object containing errors detected during parsing.
-        /// Instance of newly created OpenApiDocument.
-        public OpenApiDocument Read(Stream input, out OpenApiDiagnostic diagnostic)
-        {
-            using var reader = new StreamReader(input, Encoding.UTF8, true, 4096, _settings.LeaveStreamOpen);
-            return new OpenApiTextReaderReader(_settings).Read(reader, out diagnostic);
-        }
-
-        /// 
-        /// Reads the stream input and parses it into an Open API document.
-        /// 
-        /// Stream containing OpenAPI description to parse.
-        /// Cancellation token.
-        /// Instance result containing newly created OpenApiDocument and diagnostics object from the process
-        public async Task ReadAsync(Stream input, CancellationToken cancellationToken = default)
-        {
-            MemoryStream bufferedStream;
-            int bufferSize = 4096;
-            if (input is MemoryStream stream)
-            {
-                bufferedStream = stream;
-            }
-            else
-            {
-                // Buffer stream so that OpenApiTextReaderReader can process it synchronously
-                // YamlDocument doesn't support async reading.
-                bufferedStream = new();
-                bufferSize = 81920;
-                await input.CopyToAsync(bufferedStream, bufferSize, cancellationToken);
-                bufferedStream.Position = 0;
-            }
-
-            using var reader = new StreamReader(bufferedStream, Encoding.UTF8, true, bufferSize, _settings.LeaveStreamOpen);
-            return await new OpenApiTextReaderReader(_settings).ReadAsync(reader, cancellationToken);
-        }
-
-        /// 
-        /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element.
-        /// 
-        /// Stream containing OpenAPI description to parse.
-        /// Version of the OpenAPI specification that the fragment conforms to.
-        /// Returns diagnostic object containing errors detected during parsing
-        /// Instance of newly created OpenApiDocument
-        public T ReadFragment(Stream input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiReferenceable
-        {
-            using var reader = new StreamReader(input, Encoding.UTF8, true, 4096, _settings.LeaveStreamOpen);
-            return new OpenApiTextReaderReader(_settings).ReadFragment(reader, version, out diagnostic);
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiStringReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiStringReader.cs
deleted file mode 100644
index 1a694f255..000000000
--- a/src/Microsoft.OpenApi.Readers/OpenApiStringReader.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System.IO;
-using Microsoft.OpenApi.Interfaces;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.Interface;
-
-namespace Microsoft.OpenApi.Readers
-{
-    /// 
-    /// Service class for converting strings into OpenApiDocument instances
-    /// 
-    public class OpenApiStringReader : IOpenApiReader
-    {
-        private readonly OpenApiReaderSettings _settings;
-
-        /// 
-        /// Constructor tha allows reader to use non-default settings
-        /// 
-        /// 
-        public OpenApiStringReader(OpenApiReaderSettings settings = null)
-        {
-            _settings = settings ?? new OpenApiReaderSettings();
-        }
-
-        /// 
-        /// Reads the string input and parses it into an Open API document.
-        /// 
-        public OpenApiDocument Read(string input, out OpenApiDiagnostic diagnostic)
-        {
-            using var reader = new StringReader(input);
-            return new OpenApiTextReaderReader(_settings).Read(reader, out diagnostic);
-        }
-
-        /// 
-        /// Reads the string input and parses it into an Open API element.
-        /// 
-        public T ReadFragment(string input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
-        {
-            using var reader = new StringReader(input);
-            return new OpenApiTextReaderReader(_settings).ReadFragment(reader, version, out diagnostic);
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs
deleted file mode 100644
index dff20fc7f..000000000
--- a/src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.OpenApi.Interfaces;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.Interface;
-using SharpYaml;
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers
-{
-    /// 
-    /// Service class for converting contents of TextReader into OpenApiDocument instances
-    /// 
-    public class OpenApiTextReaderReader : IOpenApiReader
-    {
-        private readonly OpenApiReaderSettings _settings;
-
-        /// 
-        /// Create stream reader with custom settings if desired.
-        /// 
-        /// 
-        public OpenApiTextReaderReader(OpenApiReaderSettings settings = null)
-        {
-            _settings = settings ?? new OpenApiReaderSettings();
-        }
-
-        /// 
-        /// Reads the stream input and parses it into an Open API document.
-        /// 
-        /// TextReader containing OpenAPI description to parse.
-        /// Returns diagnostic object containing errors detected during parsing
-        /// Instance of newly created OpenApiDocument
-        public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
-        {
-            YamlDocument yamlDocument;
-
-            // Parse the YAML/JSON text in the TextReader into the YamlDocument
-            try
-            {
-                yamlDocument = LoadYamlDocument(input);
-            }
-            catch (YamlException ex)
-            {
-                diagnostic = new();
-                diagnostic.Errors.Add(new($"#line={ex.Start.Line}", ex.Message));
-                return new();
-            }
-
-            return new OpenApiYamlDocumentReader(this._settings).Read(yamlDocument, out diagnostic);
-        }
-
-        /// 
-        /// Reads the content of the TextReader.  If there are references to external documents then they will be read asynchronously.
-        /// 
-        /// TextReader containing OpenAPI description to parse.
-        /// Cancellation token.
-        /// A ReadResult instance that contains the resulting OpenApiDocument and a diagnostics instance.
-        public async Task ReadAsync(TextReader input, CancellationToken cancellationToken = default)
-        {
-            YamlDocument yamlDocument;
-
-            // Parse the YAML/JSON text in the TextReader into the YamlDocument
-            try
-            {
-                yamlDocument = LoadYamlDocument(input);
-            }
-            catch (YamlException ex)
-            {
-                var diagnostic = new OpenApiDiagnostic();
-                diagnostic.Errors.Add(new($"#line={ex.Start.Line}", ex.Message));
-                return new()
-                {
-                    OpenApiDocument = null,
-                    OpenApiDiagnostic = diagnostic
-                };
-            }
-
-            return await new OpenApiYamlDocumentReader(this._settings).ReadAsync(yamlDocument, cancellationToken);
-        }
-
-        /// 
-        /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element.
-        /// 
-        /// TextReader containing OpenAPI description to parse.
-        /// Version of the OpenAPI specification that the fragment conforms to.
-        /// Returns diagnostic object containing errors detected during parsing
-        /// Instance of newly created OpenApiDocument
-        public T ReadFragment(TextReader input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
-        {
-            YamlDocument yamlDocument;
-
-            // Parse the YAML/JSON
-            try
-            {
-                yamlDocument = LoadYamlDocument(input);
-            }
-            catch (YamlException ex)
-            {
-                diagnostic = new();
-                diagnostic.Errors.Add(new($"#line={ex.Start.Line}", ex.Message));
-                return default;
-            }
-
-            return new OpenApiYamlDocumentReader(this._settings).ReadFragment(yamlDocument, version, out diagnostic);
-        }
-
-        /// 
-        /// Helper method to turn streams into YamlDocument
-        /// 
-        /// Stream containing YAML formatted text
-        /// Instance of a YamlDocument
-        static YamlDocument LoadYamlDocument(TextReader input)
-        {
-            var yamlStream = new YamlStream();
-            yamlStream.Load(input);
-            return yamlStream.Documents.First();
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
deleted file mode 100644
index af9ebcad1..000000000
--- a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.OpenApi.Exceptions;
-using Microsoft.OpenApi.Extensions;
-using Microsoft.OpenApi.Interfaces;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.Interface;
-using Microsoft.OpenApi.Readers.Services;
-using Microsoft.OpenApi.Services;
-using Microsoft.OpenApi.Validations;
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers
-{
-    /// 
-    /// Service class for converting contents of TextReader into OpenApiDocument instances
-    /// 
-    internal class OpenApiYamlDocumentReader : IOpenApiReader
-    {
-        private readonly OpenApiReaderSettings _settings;
-
-        /// 
-        /// Create stream reader with custom settings if desired.
-        /// 
-        /// 
-        public OpenApiYamlDocumentReader(OpenApiReaderSettings settings = null)
-        {
-            _settings = settings ?? new OpenApiReaderSettings();
-        }
-
-        /// 
-        /// Reads the stream input and parses it into an Open API document.
-        /// 
-        /// TextReader containing OpenAPI description to parse.
-        /// Returns diagnostic object containing errors detected during parsing
-        /// Instance of newly created OpenApiDocument
-        public OpenApiDocument Read(YamlDocument input, out OpenApiDiagnostic diagnostic)
-        {
-            diagnostic = new();
-            var context = new ParsingContext(diagnostic)
-            {
-                ExtensionParsers = _settings.ExtensionParsers,
-                BaseUrl = _settings.BaseUrl,
-                DefaultContentType = _settings.DefaultContentType
-            };
-
-            OpenApiDocument document = null;
-            try
-            {
-                // Parse the OpenAPI Document
-                document = context.Parse(input);
-
-                if (_settings.LoadExternalRefs)
-                {
-                    throw new InvalidOperationException("Cannot load external refs using the synchronous Read, use ReadAsync instead.");
-                }
-
-                ResolveReferences(diagnostic, document);
-            }
-            catch (OpenApiException ex)
-            {
-                diagnostic.Errors.Add(new(ex));
-            }
-
-            // Validate the document
-            if (_settings.RuleSet != null && _settings.RuleSet.Rules.Count > 0)
-            {
-                var openApiErrors = document.Validate(_settings.RuleSet);
-                foreach (var item in openApiErrors.OfType())
-                {
-                    diagnostic.Errors.Add(item);
-                }
-                foreach (var item in openApiErrors.OfType())
-                {
-                    diagnostic.Warnings.Add(item);
-                }
-            }
-
-            return document;
-        }
-
-        public async Task ReadAsync(YamlDocument input, CancellationToken cancellationToken = default)
-        {
-            var diagnostic = new OpenApiDiagnostic();
-            var context = new ParsingContext(diagnostic)
-            {
-                ExtensionParsers = _settings.ExtensionParsers,
-                BaseUrl = _settings.BaseUrl
-            };
-
-            OpenApiDocument document = null;
-            try
-            {
-                // Parse the OpenAPI Document
-                document = context.Parse(input);
-
-                if (_settings.LoadExternalRefs)
-                {
-                    var diagnosticExternalRefs = await LoadExternalRefsAsync(document, cancellationToken);
-                    // Merge diagnostics of external reference
-                    if (diagnosticExternalRefs != null)
-                    {
-                        diagnostic.Errors.AddRange(diagnosticExternalRefs.Errors);
-                        diagnostic.Warnings.AddRange(diagnosticExternalRefs.Warnings);
-                    }
-                }
-
-                ResolveReferences(diagnostic, document);
-            }
-            catch (OpenApiException ex)
-            {
-                diagnostic.Errors.Add(new(ex));
-            }
-
-            // Validate the document
-            if (_settings.RuleSet != null && _settings.RuleSet.Rules.Count > 0)
-            {
-                var openApiErrors = document.Validate(_settings.RuleSet);
-                foreach (var item in openApiErrors.OfType())
-                {
-                    diagnostic.Errors.Add(item);
-                }
-                foreach (var item in openApiErrors.OfType())
-                {
-                    diagnostic.Warnings.Add(item);
-                }
-            }
-
-            return new()
-            {
-                OpenApiDocument = document,
-                OpenApiDiagnostic = diagnostic
-            };
-        }
-
-        private Task LoadExternalRefsAsync(OpenApiDocument document, CancellationToken cancellationToken = default)
-        {
-            // Create workspace for all documents to live in.
-            var openApiWorkSpace = new OpenApiWorkspace();
-
-            // Load this root document into the workspace
-            var streamLoader = new DefaultStreamLoader(_settings.BaseUrl);
-            var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, _settings.CustomExternalLoader ?? streamLoader, _settings);
-            return workspaceLoader.LoadAsync(new() { ExternalResource = "/" }, document, null, cancellationToken);
-        }
-
-        private void ResolveReferences(OpenApiDiagnostic diagnostic, OpenApiDocument document)
-        {
-            var errors = new List();
-
-            // Resolve References if requested
-            switch (_settings.ReferenceResolution)
-            {
-                case ReferenceResolutionSetting.ResolveAllReferences:
-                    throw new ArgumentException("Resolving external references is not supported");
-                case ReferenceResolutionSetting.ResolveLocalReferences:
-                    errors.AddRange(document.ResolveReferences());
-                    break;
-                case ReferenceResolutionSetting.DoNotResolveReferences:
-                    break;
-            }
-
-            foreach (var item in errors)
-            {
-                diagnostic.Errors.Add(item);
-            }
-        }
-
-        /// 
-        /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element.
-        /// 
-        /// TextReader containing OpenAPI description to parse.
-        /// Version of the OpenAPI specification that the fragment conforms to.
-        /// Returns diagnostic object containing errors detected during parsing
-        /// Instance of newly created OpenApiDocument
-        public T ReadFragment(YamlDocument input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
-        {
-            diagnostic = new();
-            var context = new ParsingContext(diagnostic)
-            {
-                ExtensionParsers = _settings.ExtensionParsers
-            };
-
-            IOpenApiElement element = null;
-            try
-            {
-                // Parse the OpenAPI element
-                element = context.ParseFragment(input, version);
-            }
-            catch (OpenApiException ex)
-            {
-                diagnostic.Errors.Add(new(ex));
-            }
-
-            // Validate the element
-            if (_settings.RuleSet != null && _settings.RuleSet.Rules.Count > 0)
-            {
-                var errors = element.Validate(_settings.RuleSet);
-                foreach (var item in errors)
-                {
-                    diagnostic.Errors.Add(item);
-                }
-            }
-
-            return (T)element;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs
new file mode 100644
index 000000000..cff6dd1da
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs
@@ -0,0 +1,96 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.IO;
+using System.Text.Json.Nodes;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.OpenApi.Interfaces;
+using Microsoft.OpenApi.Reader;
+using SharpYaml.Serialization;
+using System.Linq;
+using Microsoft.OpenApi.Models;
+
+namespace Microsoft.OpenApi.Readers
+{
+    /// 
+    /// Reader for parsing YAML files into an OpenAPI document.
+    /// 
+    public class OpenApiYamlReader : IOpenApiReader
+    {
+        /// 
+        public async Task ReadAsync(TextReader input,
+                                                OpenApiReaderSettings settings = null,
+                                                CancellationToken cancellationToken = default)
+        {
+            JsonNode jsonNode;
+
+            // Parse the YAML text in the TextReader into a sequence of JsonNodes
+            try
+            {
+                jsonNode = LoadJsonNodesFromYamlDocument(input);
+            }
+            catch (JsonException ex)
+            {
+                var diagnostic = new OpenApiDiagnostic();
+                diagnostic.Errors.Add(new($"#line={ex.LineNumber}", ex.Message));
+                return new()
+                {
+                    OpenApiDocument = null,
+                    OpenApiDiagnostic = diagnostic
+                };
+            }
+
+            return await ReadAsync(jsonNode, settings, cancellationToken: cancellationToken);
+        }
+
+        /// 
+        public T ReadFragment(TextReader input,
+                                 OpenApiSpecVersion version,
+                                 out OpenApiDiagnostic diagnostic,
+                                 OpenApiReaderSettings settings = null) where T : IOpenApiElement
+        {
+            JsonNode jsonNode;
+
+            // Parse the YAML
+            try
+            {
+                jsonNode = LoadJsonNodesFromYamlDocument(input);
+            }
+            catch (JsonException ex)
+            {
+                diagnostic = new();
+                diagnostic.Errors.Add(new($"#line={ex.LineNumber}", ex.Message));
+                return default;
+            }
+
+            return ReadFragment(jsonNode, version, out diagnostic);
+        }
+
+        /// 
+        /// Helper method to turn streams into a sequence of JsonNodes
+        /// 
+        /// Stream containing YAML formatted text
+        /// Instance of a YamlDocument
+        static JsonNode LoadJsonNodesFromYamlDocument(TextReader input)
+        {
+            var yamlStream = new YamlStream();
+            yamlStream.Load(input);
+            var yamlDocument = yamlStream.Documents.First();
+            return yamlDocument.ToJsonNode();
+        }
+
+        ///         
+        public async Task ReadAsync(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null, CancellationToken cancellationToken = default)
+        {
+            return await OpenApiReaderRegistry.DefaultReader.ReadAsync(jsonNode, settings, OpenApiConstants.Yaml, cancellationToken);
+        }
+
+        /// 
+        public T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement
+        {
+            return OpenApiReaderRegistry.DefaultReader.ReadFragment(input, version, out diagnostic);
+        }
+    }
+}
diff --git a/src/Microsoft.OpenApi.Readers/ParseNodes/JsonPointerExtensions.cs b/src/Microsoft.OpenApi.Readers/ParseNodes/JsonPointerExtensions.cs
deleted file mode 100644
index 412d6901b..000000000
--- a/src/Microsoft.OpenApi.Readers/ParseNodes/JsonPointerExtensions.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers.ParseNodes
-{
-    /// 
-    /// Extensions for JSON pointers.
-    /// 
-    public static class JsonPointerExtensions
-    {
-        /// 
-        /// Finds the YAML node that corresponds to this JSON pointer based on the base YAML node.
-        /// 
-        public static YamlNode Find(this JsonPointer currentPointer, YamlNode baseYamlNode)
-        {
-            if (currentPointer.Tokens.Length == 0)
-            {
-                return baseYamlNode;
-            }
-
-            try
-            {
-                var pointer = baseYamlNode;
-                foreach (var token in currentPointer.Tokens)
-                {
-                    if (pointer is YamlSequenceNode sequence)
-                    {
-                        pointer = sequence.Children[Convert.ToInt32(token)];
-                    }
-                    else
-                    {
-                        if (pointer is YamlMappingNode map)
-                        {
-                            if (!map.Children.TryGetValue(new YamlScalarNode(token), out pointer))
-                            {
-                                return null;
-                            }
-                        }
-                    }
-                }
-
-                return pointer;
-            }
-            catch (Exception)
-            {
-                return null;
-            }
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/ParseNodes/MapNode.cs b/src/Microsoft.OpenApi.Readers/ParseNodes/MapNode.cs
deleted file mode 100644
index 61f609817..000000000
--- a/src/Microsoft.OpenApi.Readers/ParseNodes/MapNode.cs
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.OpenApi.Any;
-using Microsoft.OpenApi.Interfaces;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.Exceptions;
-using SharpYaml.Schemas;
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers.ParseNodes
-{
-    /// 
-    /// Abstraction of a Map to isolate semantic parsing from details of
-    /// 
-    internal class MapNode : ParseNode, IEnumerable
-    {
-        private readonly YamlMappingNode _node;
-        private readonly List _nodes;
-
-        public MapNode(ParsingContext context, string yamlString) :
-            this(context, (YamlMappingNode)YamlHelper.ParseYamlString(yamlString))
-        {
-        }
-
-        public MapNode(ParsingContext context, YamlNode node) : base(
-            context)
-        {
-            if (node is not YamlMappingNode mapNode)
-            {
-                throw new OpenApiReaderException("Expected map.", Context);
-            }
-
-            this._node = mapNode;
-
-            _nodes = this._node.Children
-                .Select(kvp => new PropertyNode(Context, kvp.Key.GetScalarValue(), kvp.Value))
-                .Cast()
-                .ToList();
-        }
-
-        public PropertyNode this[string key]
-        {
-            get
-            {
-                if (this._node.Children.TryGetValue(new YamlScalarNode(key), out var node))
-                {
-                    return new(Context, key, node);
-                }
-
-                return null;
-            }
-        }
-
-        public override Dictionary CreateMap(Func map)
-        {
-            var yamlMap = _node;
-            if (yamlMap == null)
-            {
-                throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context);
-            }
-
-            var nodes = yamlMap.Select(
-                n =>
-                {
-                    var key = n.Key.GetScalarValue();
-                    T value;
-                    try
-                    {
-                        Context.StartObject(key);
-                        value = n.Value as YamlMappingNode == null
-                          ? default
-                          : map(new(Context, n.Value as YamlMappingNode));
-                    }
-                    finally
-                    {
-                        Context.EndObject();
-                    }
-                    return new
-                    {
-                        key = key,
-                        value = value
-                    };
-                });
-
-            return nodes.ToDictionary(k => k.key, v => v.value);
-        }
-
-        public override Dictionary CreateMapWithReference(
-            ReferenceType referenceType,
-            Func map)
-        {
-            var yamlMap = _node;
-            if (yamlMap == null)
-            {
-                throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context);
-            }
-
-            var nodes = yamlMap.Select(
-                n =>
-                {
-                    var key = n.Key.GetScalarValue();
-                    (string key, T value) entry;
-                    try
-                    {
-                        Context.StartObject(key);
-                        entry = (
-                            key: key,
-                            value: map(new(Context, (YamlMappingNode)n.Value))
-                        );
-                        if (entry.value == null)
-                        {
-                            return default;  // Body Parameters shouldn't be converted to Parameters
-                        }
-                        // If the component isn't a reference to another component, then point it to itself.
-                        if (entry.value.Reference == null)
-                        {
-                            entry.value.Reference = new()
-                            {
-                                Type = referenceType,
-                                Id = entry.key
-                            };
-                        }
-                    }
-                    finally
-                    {
-                        Context.EndObject();
-                    }
-                    return entry;
-                }
-                );
-            return nodes.Where(n => n != default).ToDictionary(k => k.key, v => v.value);
-        }
-
-        public override Dictionary CreateSimpleMap(Func map)
-        {
-            var yamlMap = _node;
-            if (yamlMap == null)
-            {
-                throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context);
-            }
-
-            var nodes = yamlMap.Select(
-                n =>
-                {
-                    var key = n.Key.GetScalarValue();
-                    try
-                    {
-                        Context.StartObject(key);
-                        if (n.Value is not YamlScalarNode scalarNode)
-                        {
-                            throw new OpenApiReaderException($"Expected scalar while parsing {typeof(T).Name}", Context);
-                        }
-                        return (key, value: map(new(Context, (YamlScalarNode)n.Value)));
-                    } finally {
-                        Context.EndObject();
-                    }
-                });
-            return nodes.ToDictionary(k => k.key, v => v.value);
-        }
-
-        public IEnumerator GetEnumerator()
-        {
-            return _nodes.GetEnumerator();
-        }
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _nodes.GetEnumerator();
-        }
-
-        public override string GetRaw()
-        {
-            var x = new Serializer(new(new JsonSchema()) { EmitJsonComptible = true });
-            return x.Serialize(_node);
-        }
-
-        public T GetReferencedObject(ReferenceType referenceType, string referenceId)
-            where T : IOpenApiReferenceable, new()
-        {
-            return new()
-            {
-                UnresolvedReference = true,
-                Reference = Context.VersionService.ConvertToOpenApiReference(referenceId, referenceType)
-            };
-        }
-
-        public string GetReferencePointer()
-        {
-            if (!_node.Children.TryGetValue(new YamlScalarNode("$ref"), out var refNode))
-            {
-                return null;
-            }
-
-            return refNode.GetScalarValue();
-        }
-
-        public string GetScalarValue(ValueNode key)
-        {
-            if (_node.Children[new YamlScalarNode(key.GetScalarValue())] is not YamlScalarNode scalarNode)
-            {
-                throw new OpenApiReaderException($"Expected scalar at line {_node.Start.Line} for key {key.GetScalarValue()}", Context);
-            }
-
-            return scalarNode.Value;
-        }
-
-        /// 
-        /// Create a 
-        /// 
-        /// The created Any object.
-        public override IOpenApiAny CreateAny()
-        {
-            var apiObject = new OpenApiObject();
-            foreach (var node in this)
-            {
-                apiObject.Add(node.Name, node.Value.CreateAny());
-            }
-
-            return apiObject;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs b/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs
deleted file mode 100644
index 2c0a45379..000000000
--- a/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using Microsoft.OpenApi.Any;
-using Microsoft.OpenApi.Models;
-
-namespace Microsoft.OpenApi.Readers.ParseNodes
-{
-    internal static class OpenApiAnyConverter
-    {
-        /// 
-        /// Converts the s in the given 
-        /// into the appropriate  type based on the given .
-        /// For those strings that the schema does not specify the type for, convert them into
-        /// the most specific type based on the value.
-        /// 
-        public static IOpenApiAny GetSpecificOpenApiAny(IOpenApiAny openApiAny, OpenApiSchema schema = null)
-        {
-            if (openApiAny is OpenApiArray openApiArray)
-            {
-                var newArray = new OpenApiArray();
-                foreach (var element in openApiArray)
-                {
-                    newArray.Add(GetSpecificOpenApiAny(element, schema?.Items));
-                }
-
-                return newArray;
-            }
-
-            if (openApiAny is OpenApiObject openApiObject)
-            {
-                var newObject = new OpenApiObject();
-
-                foreach (var key in openApiObject.Keys.ToList())
-                {
-                    if (schema?.Properties != null && schema.Properties.TryGetValue(key, out var property))
-                    {
-                        newObject[key] = GetSpecificOpenApiAny(openApiObject[key], property);
-                    }
-                    else
-                    {
-                        newObject[key] = GetSpecificOpenApiAny(openApiObject[key], schema?.AdditionalProperties);
-                    }
-                }
-
-                return newObject;
-            }
-
-            if (openApiAny is not OpenApiString apiString)
-            {
-                return openApiAny;
-            }
-
-            var value = apiString.Value;
-            var type = schema?.Type;
-            var format = schema?.Format;
-
-            if (apiString.IsExplicit())
-            {
-                // More narrow type detection for explicit strings, only check types that are passed as strings
-                if (schema == null)
-                {
-                    if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue))
-                    {
-                        // if the time component is exactly midnight(00:00:00) meaning no time has elapsed, return a date-only value
-                        return dateTimeValue.TimeOfDay == TimeSpan.Zero ? new OpenApiDate(dateTimeValue.Date) 
-                            : new OpenApiDateTime(dateTimeValue);
-                    }
-                }
-                else if (type == "string")
-                {
-                    if (format == "byte")
-                    {
-                        try
-                        {
-                            return new OpenApiByte(Convert.FromBase64String(value));
-                        }
-                        catch (FormatException)
-                        { }
-                    }
-
-                    if (format == "binary")
-                    {
-                        try
-                        {
-                            return new OpenApiBinary(Encoding.UTF8.GetBytes(value));
-                        }
-                        catch (EncoderFallbackException)
-                        { }
-                    }
-
-                    if (format == "date")
-                    {
-                        if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateValue))
-                        {
-                            return new OpenApiDate(dateValue.Date);
-                        }
-                    }
-
-                    if (format == "date-time")
-                    {
-                        if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue))
-                        {
-                            return new OpenApiDateTime(dateTimeValue);
-                        }
-                    }
-
-                    if (format == "password")
-                    {
-                        return new OpenApiPassword(value);
-                    }
-                }
-
-                return apiString;
-            }
-
-            if (value is null or "null")
-            {
-                return new OpenApiNull();
-            }
-
-            if (schema?.Type == null)
-            {
-                if (value == "true")
-                {
-                    return new OpenApiBoolean(true);
-                }
-
-                if (value == "false")
-                {
-                    return new OpenApiBoolean(false);
-                }
-
-                if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue))
-                {
-                    return new OpenApiInteger(intValue);
-                }
-
-                if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue))
-                {
-                    return new OpenApiLong(longValue);
-                }
-
-                if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue))
-                {
-                    return new OpenApiDouble(doubleValue);
-                }
-
-                if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue))
-                {
-                    return new OpenApiDateTime(dateTimeValue);
-                }
-            }
-            else
-            {
-                if (type is "integer" or "number" && format == "int32")
-                {
-                    if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue))
-                    {
-                        return new OpenApiInteger(intValue);
-                    }
-                }
-
-                if (type is "integer" or "number" && format == "int64")
-                {
-                    if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue))
-                    {
-                        return new OpenApiLong(longValue);
-                    }
-                }
-
-                if (type == "integer")
-                {
-                    if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue))
-                    {
-                        return new OpenApiInteger(intValue);
-                    }
-                }
-
-                if (type == "number" && format == "float")
-                {
-                    if (float.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var floatValue))
-                    {
-                        return new OpenApiFloat(floatValue);
-                    }
-                }
-
-                if (type == "number" && format == "double")
-                {
-                    if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue))
-                    {
-                        return new OpenApiDouble(doubleValue);
-                    }
-                }
-
-                if (type == "number")
-                {
-                    if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var doubleValue))
-                    {
-                        return new OpenApiDouble(doubleValue);
-                    }
-                }
-
-                if (type == "string" && format == "byte")
-                {
-                    try
-                    {
-                        return new OpenApiByte(Convert.FromBase64String(value));
-                    }
-                    catch (FormatException)
-                    { }
-                }
-
-                // binary
-                if (type == "string" && format == "binary")
-                {
-                    try
-                    {
-                        return new OpenApiBinary(Encoding.UTF8.GetBytes(value));
-                    }
-                    catch (EncoderFallbackException)
-                    { }
-                }
-
-                if (type == "string" && format == "date")
-                {
-                    if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateValue))
-                    {
-                        return new OpenApiDate(dateValue.Date);
-                    }
-                }
-
-                if (type == "string" && format == "date-time")
-                {
-                    if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue))
-                    {
-                        return new OpenApiDateTime(dateTimeValue);
-                    }
-                }
-
-                if (type == "string" && format == "password")
-                {
-                    return new OpenApiPassword(value);
-                }
-
-                if (type == "string")
-                {
-                    return apiString;
-                }
-
-                if (type == "boolean")
-                {
-                    if (bool.TryParse(value, out var booleanValue))
-                    {
-                        return new OpenApiBoolean(booleanValue);
-                    }
-                }
-            }
-
-            // If data conflicts with the given type, return a string.
-            // This converter is used in the parser, so it does not perform any validations,
-            // but the validator can be used to validate whether the data and given type conflicts.
-            return apiString;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/ParseNodes/RootNode.cs b/src/Microsoft.OpenApi.Readers/ParseNodes/RootNode.cs
deleted file mode 100644
index f70b9ca99..000000000
--- a/src/Microsoft.OpenApi.Readers/ParseNodes/RootNode.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers.ParseNodes
-{
-    /// 
-    /// Wrapper class around YamlDocument to isolate semantic parsing from details of Yaml DOM.
-    /// 
-    internal class RootNode : ParseNode
-    {
-        private readonly YamlDocument _yamlDocument;
-
-        public RootNode(
-            ParsingContext context,
-            YamlDocument yamlDocument) : base(context)
-        {
-            _yamlDocument = yamlDocument;
-        }
-
-        public ParseNode Find(JsonPointer referencePointer)
-        {
-            var yamlNode = referencePointer.Find(_yamlDocument.RootNode);
-            if (yamlNode == null)
-            {
-                return null;
-            }
-
-            return Create(Context, yamlNode);
-        }
-
-        public MapNode GetMap()
-        {
-            return new(Context, (YamlMappingNode)_yamlDocument.RootNode);
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/ParseNodes/ValueNode.cs b/src/Microsoft.OpenApi.Readers/ParseNodes/ValueNode.cs
deleted file mode 100644
index 1aeccb8e7..000000000
--- a/src/Microsoft.OpenApi.Readers/ParseNodes/ValueNode.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Any;
-using Microsoft.OpenApi.Readers.Exceptions;
-using SharpYaml;
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers.ParseNodes
-{
-    internal class ValueNode : ParseNode
-    {
-        private readonly YamlScalarNode _node;
-
-        public ValueNode(ParsingContext context, YamlNode node) : base(
-            context)
-        {
-            if (node is not YamlScalarNode scalarNode)
-            {
-                throw new OpenApiReaderException("Expected a value.", node);
-            }
-            _node = scalarNode;
-        }
-
-        public override string GetScalarValue()
-        {
-            return _node.Value;
-        }
-
-        /// 
-        /// Create a 
-        /// 
-        /// The created Any object.
-        public override IOpenApiAny CreateAny()
-        {
-            var value = GetScalarValue();
-            return new OpenApiString(value, this._node.Style is ScalarStyle.SingleQuoted or ScalarStyle.DoubleQuoted or ScalarStyle.Literal or ScalarStyle.Folded);
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/Properties/SRResource.Designer.cs b/src/Microsoft.OpenApi.Readers/Properties/SRResource.Designer.cs
index e8bbc567e..a35dab766 100644
--- a/src/Microsoft.OpenApi.Readers/Properties/SRResource.Designer.cs
+++ b/src/Microsoft.OpenApi.Readers/Properties/SRResource.Designer.cs
@@ -8,7 +8,7 @@
 // 
 //------------------------------------------------------------------------------
 
-namespace Microsoft.OpenApi.Readers.Properties {
+namespace Microsoft.OpenApi.Reader.Properties {
     using System;
     
     
@@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.Readers.Properties {
     // class via a tool like ResGen or Visual Studio.
     // To add or remove a member, edit your .ResX file then rerun ResGen
     // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class SRResource {
diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs
deleted file mode 100644
index ff873f4a0..000000000
--- a/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using System.Globalization;
-using Microsoft.OpenApi.Extensions;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.Exceptions;
-using Microsoft.OpenApi.Readers.ParseNodes;
-
-namespace Microsoft.OpenApi.Readers.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 _headerFixedFields = new()
-        {
-            {
-                "description",
-                (o, n) => o.Description = n.GetScalarValue()
-            },
-            {
-                "type",
-                (o, n) => GetOrCreateSchema(o).Type = n.GetScalarValue()
-            },
-            {
-                "format",
-                (o, n) => GetOrCreateSchema(o).Format = n.GetScalarValue()
-            },
-            {
-                "items",
-                (o, n) => GetOrCreateSchema(o).Items = LoadSchema(n)
-            },
-            {
-                "collectionFormat",
-                (o, n) => LoadStyle(o, n.GetScalarValue())
-            },
-            {
-                "default",
-                (o, n) => GetOrCreateSchema(o).Default = n.CreateAny()
-            },
-            {
-                "maximum",
-                (o, n) => GetOrCreateSchema(o).Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
-            },
-            {
-                "exclusiveMaximum",
-                (o, n) => GetOrCreateSchema(o).ExclusiveMaximum = bool.Parse(n.GetScalarValue())
-            },
-            {
-                "minimum",
-                (o, n) => GetOrCreateSchema(o).Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
-            },
-            {
-                "exclusiveMinimum",
-                (o, n) => GetOrCreateSchema(o).ExclusiveMinimum = bool.Parse(n.GetScalarValue())
-            },
-            {
-                "maxLength",
-                (o, n) => GetOrCreateSchema(o).MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
-            },
-            {
-                "minLength",
-                (o, n) => GetOrCreateSchema(o).MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
-            },
-            {
-                "pattern",
-                (o, n) => GetOrCreateSchema(o).Pattern = n.GetScalarValue()
-            },
-            {
-                "maxItems",
-                (o, n) => GetOrCreateSchema(o).MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
-            },
-            {
-                "minItems",
-                (o, n) => GetOrCreateSchema(o).MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
-            },
-            {
-                "uniqueItems",
-                (o, n) => GetOrCreateSchema(o).UniqueItems = bool.Parse(n.GetScalarValue())
-            },
-            {
-                "multipleOf",
-                (o, n) => GetOrCreateSchema(o).MultipleOf = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
-            },
-            {
-                "enum",
-                (o, n) => GetOrCreateSchema(o).Enum = n.CreateListOfAny()
-            }
-        };
-
-        private static readonly PatternFieldMap _headerPatternFields = new()
-        {
-            {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
-        };
-
-        private static readonly AnyFieldMap _headerAnyFields =
-            new()
-            {
-                {
-                    OpenApiConstants.Default,
-                    new(
-                        p => p.Schema?.Default,
-                        (p, v) =>
-                        {
-                            if(p.Schema == null) return;
-                            p.Schema.Default = v;
-                        },
-                        p => p.Schema)
-                }
-            };
-
-        private static readonly AnyListFieldMap _headerAnyListFields =
-            new()
-            {
-                {
-                    OpenApiConstants.Enum,
-                    new(
-                        p => p.Schema?.Enum,
-                        (p, v) =>
-                        {
-                            if(p.Schema == null) return;
-                            p.Schema.Enum = v;
-                        },
-                        p => p.Schema)
-                },
-            };
-
-        public static OpenApiHeader LoadHeader(ParseNode node)
-        {
-            var mapNode = node.CheckMapNode("header");
-            var header = new OpenApiHeader();
-            foreach (var property in mapNode)
-            {
-                property.ParseField(header, _headerFixedFields, _headerPatternFields);
-            }
-
-            var schema = node.Context.GetFromTempStorage("schema");
-            if (schema != null)
-            {
-                header.Schema = schema;
-                node.Context.SetTempStorage("schema", null);
-            }
-
-            ProcessAnyFields(mapNode, header, _headerAnyFields);
-            ProcessAnyListFields(mapNode, header, _headerAnyListFields);
-
-            return header;
-        }
-
-        private static void LoadStyle(OpenApiHeader header, string style)
-        {
-            switch (style)
-            {
-                case "csv":
-                    header.Style = ParameterStyle.Simple;
-                    return;
-                case "ssv":
-                    header.Style = ParameterStyle.SpaceDelimited;
-                    return;
-                case "pipes":
-                    header.Style = ParameterStyle.PipeDelimited;
-                    return;
-                case "tsv":
-                    throw new NotSupportedException();
-                default:
-                    throw new OpenApiReaderException("Unrecognized header style: " + style);
-            }
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs
deleted file mode 100644
index dd884d574..000000000
--- a/src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Microsoft.OpenApi.Extensions;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.ParseNodes;
-
-namespace Microsoft.OpenApi.Readers.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 _schemaFixedFields = 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 => n2.GetScalarValue()))
-            },
-            {
-                "enum",
-                (o, n) => o.Enum = n.CreateListOfAny()
-            },
-
-            {
-                "type",
-                (o, n) => o.Type = n.GetScalarValue()
-            },
-            {
-                "allOf",
-                (o, n) => o.AllOf = n.CreateList(LoadSchema)
-            },
-            {
-                "items",
-                (o, n) => o.Items = LoadSchema(n)
-            },
-            {
-                "properties",
-                (o, n) => o.Properties = n.CreateMap(LoadSchema)
-            },
-            {
-                "additionalProperties", (o, n) =>
-                {
-                    if (n is ValueNode)
-                    {
-                        o.AdditionalPropertiesAllowed = bool.Parse(n.GetScalarValue());
-                    }
-                    else
-                    {
-                        o.AdditionalProperties = LoadSchema(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 _schemaPatternFields = new()
-        {
-            {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
-        };
-
-        private static readonly AnyFieldMap _schemaAnyFields = new()
-        {
-            {
-                OpenApiConstants.Default,
-                new(
-                    s => s.Default,
-                    (s, v) => s.Default = v,
-                    s => s)
-            },
-            {
-                OpenApiConstants.Example,
-                new(
-                    s => s.Example,
-                    (s, v) => s.Example = v,
-                    s => s) }
-        };
-
-        private static readonly AnyListFieldMap _schemaAnyListFields = new()
-        {
-            {
-                OpenApiConstants.Enum,
-                new(
-                    s => s.Enum,
-                    (s, v) => s.Enum = v,
-                    s => s)
-            }
-        };
-
-        public static OpenApiSchema LoadSchema(ParseNode node)
-        {
-            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, _schemaFixedFields, _schemaPatternFields);
-            }
-
-            ProcessAnyFields(mapNode, schema, _schemaAnyFields);
-            ProcessAnyListFields(mapNode, schema, _schemaAnyListFields);
-
-            return schema;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiV2Deserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiV2Deserializer.cs
deleted file mode 100644
index 790940759..000000000
--- a/src/Microsoft.OpenApi.Readers/V2/OpenApiV2Deserializer.cs
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.OpenApi.Any;
-using Microsoft.OpenApi.Exceptions;
-using Microsoft.OpenApi.Interfaces;
-using Microsoft.OpenApi.Readers.ParseNodes;
-
-namespace Microsoft.OpenApi.Readers.V2
-{
-    /// 
-    /// Class containing logic to deserialize Open API V2 document into
-    /// runtime Open API object model.
-    /// 
-    internal static partial class OpenApiV2Deserializer
-    {
-        private static void ParseMap(
-            MapNode mapNode,
-            T domainObject,
-            FixedFieldMap fixedFieldMap,
-            PatternFieldMap patternFieldMap,
-            List requiredFields = null)
-        {
-            if (mapNode == null)
-            {
-                return;
-            }
-
-            var allFields = fixedFieldMap.Keys.Union(mapNode.Select(static x => x.Name));
-            foreach (var propertyNode in allFields)
-            {
-                mapNode[propertyNode]?.ParseField(domainObject, fixedFieldMap, patternFieldMap);
-                requiredFields?.Remove(propertyNode);
-            }
-        }
-
-        private static void ProcessAnyFields(
-            MapNode mapNode,
-            T domainObject,
-            AnyFieldMap anyFieldMap)
-        {
-            foreach (var anyFieldName in anyFieldMap.Keys.ToList())
-            {
-                try
-                {
-                    mapNode.Context.StartObject(anyFieldName);
-
-                    var convertedOpenApiAny = OpenApiAnyConverter.GetSpecificOpenApiAny(
-                        anyFieldMap[anyFieldName].PropertyGetter(domainObject),
-                        anyFieldMap[anyFieldName].SchemaGetter(domainObject));
-
-                    anyFieldMap[anyFieldName].PropertySetter(domainObject, convertedOpenApiAny);
-                }
-                catch (OpenApiException exception)
-                {
-                    exception.Pointer = mapNode.Context.GetLocation();
-                    mapNode.Context.Diagnostic.Errors.Add(new(exception));
-                }
-                finally
-                {
-                    mapNode.Context.EndObject();
-                }
-            }
-        }
-
-        private static void ProcessAnyListFields(
-            MapNode mapNode,
-            T domainObject,
-            AnyListFieldMap anyListFieldMap)
-        {
-            foreach (var anyListFieldName in anyListFieldMap.Keys.ToList())
-            {
-                try
-                {
-                    var newProperty = new List();
-
-                    mapNode.Context.StartObject(anyListFieldName);
-                    if (anyListFieldMap.TryGetValue(anyListFieldName, out var fieldName))
-                    {
-                        var list = fieldName.PropertyGetter(domainObject);
-                        if (list != null)
-                        {
-                            foreach (var propertyElement in list)
-                            {
-                                newProperty.Add(
-                                    OpenApiAnyConverter.GetSpecificOpenApiAny(
-                                        propertyElement,
-                                        anyListFieldMap[anyListFieldName].SchemaGetter(domainObject)));
-                            }
-                        }
-                    }
-
-                    anyListFieldMap[anyListFieldName].PropertySetter(domainObject, newProperty);
-                }
-                catch (OpenApiException exception)
-                {
-                    exception.Pointer = mapNode.Context.GetLocation();
-                    mapNode.Context.Diagnostic.Errors.Add(new(exception));
-                }
-                finally
-                {
-                    mapNode.Context.EndObject();
-                }
-            }
-        }
-
-        public static IOpenApiAny LoadAny(ParseNode node)
-        {
-            return OpenApiAnyConverter.GetSpecificOpenApiAny(node.CreateAny());
-        }
-
-        private static IOpenApiExtension LoadExtension(string name, ParseNode node)
-        {
-            if (node.Context.ExtensionParsers.TryGetValue(name, out var parser) && parser(
-                   OpenApiAnyConverter.GetSpecificOpenApiAny(node.CreateAny()),
-                   OpenApiSpecVersion.OpenApi2_0) is { } result)
-            {
-                return result;
-            }
-            else
-            {
-                return OpenApiAnyConverter.GetSpecificOpenApiAny(node.CreateAny());
-            }
-        }
-
-        private static string LoadString(ParseNode node)
-        {
-            return node.GetScalarValue();
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiComponentsDeserializer.cs
deleted file mode 100644
index 62ed95fda..000000000
--- a/src/Microsoft.OpenApi.Readers/V3/OpenApiComponentsDeserializer.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Extensions;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.ParseNodes;
-
-namespace Microsoft.OpenApi.Readers.V3
-{
-    /// 
-    /// Class containing logic to deserialize Open API V3 document into
-    /// runtime Open API object model.
-    /// 
-    internal static partial class OpenApiV3Deserializer
-    {
-        private static FixedFieldMap _componentsFixedFields = new()
-        {
-            {
-                "schemas", (o, n) => o.Schemas = n.CreateMapWithReference(ReferenceType.Schema, LoadSchema)
-            },
-            {"responses", (o, n) => o.Responses = n.CreateMapWithReference(ReferenceType.Response, LoadResponse)},
-            {"parameters", (o, n) => o.Parameters = n.CreateMapWithReference(ReferenceType.Parameter, LoadParameter)},
-            {"examples", (o, n) => o.Examples = n.CreateMapWithReference(ReferenceType.Example, LoadExample)},
-            {"requestBodies", (o, n) => o.RequestBodies = n.CreateMapWithReference(ReferenceType.RequestBody, LoadRequestBody)},
-            {"headers", (o, n) => o.Headers = n.CreateMapWithReference(ReferenceType.Header, LoadHeader)},
-            {"securitySchemes", (o, n) => o.SecuritySchemes = n.CreateMapWithReference(ReferenceType.SecurityScheme, LoadSecurityScheme)},
-            {"links", (o, n) => o.Links = n.CreateMapWithReference(ReferenceType.Link, LoadLink)},
-            {"callbacks", (o, n) => o.Callbacks = n.CreateMapWithReference(ReferenceType.Callback, LoadCallback)},
-        };
-
-        private static PatternFieldMap _componentsPatternFields =
-            new()
-            {
-                {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
-            };
-
-        public static OpenApiComponents LoadComponents(ParseNode node)
-        {
-            var mapNode = node.CheckMapNode("components");
-            var components = new OpenApiComponents();
-
-            ParseMap(mapNode, components, _componentsFixedFields, _componentsPatternFields);
-
-            return components;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiDocumentDeserializer.cs
deleted file mode 100644
index edeca23ad..000000000
--- a/src/Microsoft.OpenApi.Readers/V3/OpenApiDocumentDeserializer.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Extensions;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.ParseNodes;
-
-namespace Microsoft.OpenApi.Readers.V3
-{
-    /// 
-    /// Class containing logic to deserialize Open API V3 document into
-    /// runtime Open API object model.
-    /// 
-    internal static partial class OpenApiV3Deserializer
-    {
-        private static FixedFieldMap _openApiFixedFields = new()
-        {
-            {
-                "openapi", (_, _) =>
-                {
-                } /* Version is valid field but we already parsed it */
-            },
-            {"info", (o, n) => o.Info = LoadInfo(n)},
-            {"servers", (o, n) => o.Servers = n.CreateList(LoadServer)},
-            {"paths", (o, n) => o.Paths = LoadPaths(n)},
-            {"components", (o, n) => o.Components = LoadComponents(n)},
-            {"tags", (o, n) => {o.Tags = n.CreateList(LoadTag);
-                foreach (var tag in o.Tags)
-                {
-                    tag.Reference = new()
-                    {
-                        Id = tag.Name,
-                        Type = ReferenceType.Tag
-                    };
-                }
-            } },
-            {"externalDocs", (o, n) => o.ExternalDocs = LoadExternalDocs(n)},
-            {"security", (o, n) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement)}
-        };
-
-        private static PatternFieldMap _openApiPatternFields = new()
-        {
-            // We have no semantics to verify X- nodes, therefore treat them as just values.
-            {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
-        };
-
-        public static OpenApiDocument LoadOpenApi(RootNode rootNode)
-        {
-            var openApidoc = new OpenApiDocument();
-
-            var openApiNode = rootNode.GetMap();
-
-            ParseMap(openApiNode, openApidoc, _openApiFixedFields, _openApiPatternFields);
-
-            return openApidoc;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiPathItemDeserializer.cs
deleted file mode 100644
index f4ab2ad3b..000000000
--- a/src/Microsoft.OpenApi.Readers/V3/OpenApiPathItemDeserializer.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Extensions;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.ParseNodes;
-
-namespace Microsoft.OpenApi.Readers.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 _pathItemFixedFields = new()
-        {
-            {
-                "$ref", (o,n) => {
-                    o.Reference = new() { ExternalResource = n.GetScalarValue() };
-                    o.UnresolvedReference =true;
-                }
-            },
-            {
-                "summary",
-                (o, n) => o.Summary = n.GetScalarValue()
-            },
-            {
-                "description",
-                (o, n) => o.Description = n.GetScalarValue()
-            },
-            {"get", (o, n) => o.AddOperation(OperationType.Get, LoadOperation(n))},
-            {"put", (o, n) => o.AddOperation(OperationType.Put, LoadOperation(n))},
-            {"post", (o, n) => o.AddOperation(OperationType.Post, LoadOperation(n))},
-            {"delete", (o, n) => o.AddOperation(OperationType.Delete, LoadOperation(n))},
-            {"options", (o, n) => o.AddOperation(OperationType.Options, LoadOperation(n))},
-            {"head", (o, n) => o.AddOperation(OperationType.Head, LoadOperation(n))},
-            {"patch", (o, n) => o.AddOperation(OperationType.Patch, LoadOperation(n))},
-            {"trace", (o, n) => o.AddOperation(OperationType.Trace, LoadOperation(n))},
-            {"servers", (o, n) => o.Servers = n.CreateList(LoadServer)},
-            {"parameters", (o, n) => o.Parameters = n.CreateList(LoadParameter)}
-        };
-
-        private static readonly PatternFieldMap _pathItemPatternFields =
-            new()
-            {
-                {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}
-            };
-
-        public static OpenApiPathItem LoadPathItem(ParseNode node)
-        {
-            var mapNode = node.CheckMapNode("PathItem");
-
-            var pointer = mapNode.GetReferencePointer();
-            if (pointer != null)
-            {
-                var refObject = mapNode.GetReferencedObject(ReferenceType.Path, pointer);
-                return refObject;
-            }
-
-            var pathItem = new OpenApiPathItem();
-
-            ParseMap(mapNode, pathItem, _pathItemFixedFields, _pathItemPatternFields);
-
-            return pathItem;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs
deleted file mode 100644
index 1e386a33d..000000000
--- a/src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Extensions;
-using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.ParseNodes;
-using System.Collections.Generic;
-using System.Globalization;
-
-namespace Microsoft.OpenApi.Readers.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 _schemaFixedFields = 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 => n2.GetScalarValue()))
-            },
-            {
-                "enum",
-                (o, n) => o.Enum = n.CreateListOfAny()
-            },
-            {
-                "type",
-                (o, n) => o.Type = n.GetScalarValue()
-            },
-            {
-                "allOf",
-                (o, n) => o.AllOf = n.CreateList(LoadSchema)
-            },
-            {
-                "oneOf",
-                (o, n) => o.OneOf = n.CreateList(LoadSchema)
-            },
-            {
-                "anyOf",
-                (o, n) => o.AnyOf = n.CreateList(LoadSchema)
-            },
-            {
-                "not",
-                (o, n) => o.Not = LoadSchema(n)
-            },
-            {
-                "items",
-                (o, n) => o.Items = LoadSchema(n)
-            },
-            {
-                "properties",
-                (o, n) => o.Properties = n.CreateMap(LoadSchema)
-            },
-            {
-                "additionalProperties", (o, n) =>
-                {
-                    if (n is ValueNode)
-                    {
-                        o.AdditionalPropertiesAllowed = bool.Parse(n.GetScalarValue());
-                    }
-                    else
-                    {
-                        o.AdditionalProperties = LoadSchema(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 _schemaPatternFields = new()
-        {
-            {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}
-        };
-
-        private static readonly AnyFieldMap _schemaAnyFields = new()
-        {
-            {
-                OpenApiConstants.Default,
-                new(
-                    s => s.Default,
-                    (s, v) => s.Default = v,
-                    s => s)
-            },
-            {
-                 OpenApiConstants.Example,
-                new(
-                    s => s.Example,
-                    (s, v) => s.Example = v,
-                    s => s)
-            }
-        };
-
-        private static readonly AnyListFieldMap _schemaAnyListFields = new()
-        {
-            {
-                OpenApiConstants.Enum,
-                new(
-                    s => s.Enum,
-                    (s, v) => s.Enum = v,
-                    s => s)
-            }
-        };
-
-        public static OpenApiSchema LoadSchema(ParseNode node)
-        {
-            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, _schemaFixedFields, _schemaPatternFields);
-            }
-
-            ProcessAnyFields(mapNode, schema, _schemaAnyFields);
-            ProcessAnyListFields(mapNode, schema, _schemaAnyListFields);
-
-            return schema;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/YamlConverter.cs b/src/Microsoft.OpenApi.Readers/YamlConverter.cs
new file mode 100644
index 000000000..7d338ffa1
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlConverter.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text.Json.Nodes;
+using SharpYaml;
+using SharpYaml.Serialization;
+
+namespace Microsoft.OpenApi.Reader
+{
+    /// 
+    /// Provides extensions to convert YAML models to JSON models.
+    /// 
+    public static class YamlConverter
+    {
+        /// 
+        /// Converts all of the documents in a YAML stream to s.
+        /// 
+        /// The YAML stream.
+        /// A collection of nodes representing the YAML documents in the stream.
+        public static IEnumerable ToJsonNode(this YamlStream yaml)
+        {
+            return yaml.Documents.Select(x => x.ToJsonNode());
+        }
+
+        /// 
+        /// Converts a single YAML document to a .
+        /// 
+        /// The YAML document.
+        /// A `JsonNode` representative of the YAML document.
+        public static JsonNode ToJsonNode(this YamlDocument yaml)
+        {
+            return yaml.RootNode.ToJsonNode();
+        }
+
+        /// 
+        /// Converts a single YAML node to a .
+        /// 
+        /// The YAML node.
+        /// A `JsonNode` representative of the YAML node.
+        /// Thrown for YAML that is not compatible with JSON.
+        public static JsonNode ToJsonNode(this YamlNode yaml)
+        {
+            return yaml switch
+            {
+                YamlMappingNode map => map.ToJsonObject(),
+                YamlSequenceNode seq => seq.ToJsonArray(),
+                YamlScalarNode scalar => scalar.ToJsonValue(),
+                _ => throw new NotSupportedException("This yaml isn't convertible to JSON")
+            };
+        }
+
+        /// 
+        /// Converts a single JSON node to a .
+        /// 
+        /// 
+        /// 
+        /// 
+        public static YamlNode ToYamlNode(this JsonNode json)
+        {
+            return json switch
+            {
+                JsonObject obj => obj.ToYamlMapping(),
+                JsonArray arr => arr.ToYamlSequence(),
+                JsonValue val => val.ToYamlScalar(),
+                _ => throw new NotSupportedException("This isn't a supported JsonNode")
+            };
+        }
+
+        /// 
+        /// Converts a  to a .
+        /// 
+        /// 
+        /// 
+        public static JsonObject ToJsonObject(this YamlMappingNode yaml)
+        {
+            var node = new JsonObject();
+            foreach (var keyValuePair in yaml)
+            {
+                var key = ((YamlScalarNode)keyValuePair.Key).Value!;
+                node[key] = keyValuePair.Value.ToJsonNode();
+            }
+
+            return node;
+        }
+
+        private static YamlMappingNode ToYamlMapping(this JsonObject obj)
+        {
+            return new YamlMappingNode(obj.ToDictionary(x => (YamlNode)new YamlScalarNode(x.Key), x => x.Value!.ToYamlNode()));
+        }
+
+        /// 
+        /// Converts a  to a .
+        /// 
+        /// 
+        /// 
+        public static JsonArray ToJsonArray(this YamlSequenceNode yaml)
+        {
+            var node = new JsonArray();
+            foreach (var value in yaml)
+            {
+                node.Add(value.ToJsonNode());
+            }
+
+            return node;
+        }
+
+        private static YamlSequenceNode ToYamlSequence(this JsonArray arr)
+        {
+            return new YamlSequenceNode(arr.Select(x => x!.ToYamlNode()));
+        }
+
+        private static JsonValue ToJsonValue(this YamlScalarNode yaml)
+        {
+            switch (yaml.Style)
+            {
+                case ScalarStyle.Plain:
+                    return decimal.TryParse(yaml.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var d)
+                        ? JsonValue.Create(d)
+                        : bool.TryParse(yaml.Value, out var b)
+                            ? JsonValue.Create(b)
+                            : JsonValue.Create(yaml.Value)!;
+                case ScalarStyle.SingleQuoted:
+                case ScalarStyle.DoubleQuoted:
+                case ScalarStyle.Literal:
+                case ScalarStyle.Folded:
+                case ScalarStyle.Any:
+                    return JsonValue.Create(yaml.Value)!;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
+        private static YamlScalarNode ToYamlScalar(this JsonValue val)
+        {
+            return new YamlScalarNode(val.ToJsonString());
+        }
+    }
+}
diff --git a/src/Microsoft.OpenApi.Readers/YamlHelper.cs b/src/Microsoft.OpenApi.Readers/YamlHelper.cs
deleted file mode 100644
index 7ce58d481..000000000
--- a/src/Microsoft.OpenApi.Readers/YamlHelper.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System.IO;
-using System.Linq;
-using Microsoft.OpenApi.Exceptions;
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers
-{
-    internal static class YamlHelper
-    {
-        public static string GetScalarValue(this YamlNode node)
-        {
-            if (node is not YamlScalarNode scalarNode)
-            {
-                throw new OpenApiException($"Expected scalar at line {node.Start.Line}");
-            }
-
-            return scalarNode.Value;
-        }
-
-        public static YamlNode ParseYamlString(string yamlString)
-        {
-            var reader = new StringReader(yamlString);
-            var yamlStream = new YamlStream();
-            yamlStream.Load(reader);
-
-            var yamlDocument = yamlStream.Documents.First();
-            return yamlDocument.RootNode;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs
index 7068a61e8..d518645a5 100644
--- a/src/Microsoft.OpenApi.Workbench/MainModel.cs
+++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs
@@ -10,6 +10,7 @@
 using System.Threading.Tasks;
 using Microsoft.OpenApi.Extensions;
 using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Reader;
 using Microsoft.OpenApi.Readers;
 using Microsoft.OpenApi.Services;
 using Microsoft.OpenApi.Validations;
@@ -158,6 +159,7 @@ public OpenApiSpecVersion Version
                 _version = value;
                 OnPropertyChanged(nameof(IsV2_0));
                 OnPropertyChanged(nameof(IsV3_0));
+                OnPropertyChanged(nameof(IsV3_1));
             }
         }
 
@@ -185,6 +187,12 @@ public bool IsV3_0
             set => Version = OpenApiSpecVersion.OpenApi3_0;
         }
 
+        public bool IsV3_1
+        {
+            get => Version == OpenApiSpecVersion.OpenApi3_1;
+            set => Version = OpenApiSpecVersion.OpenApi3_1;
+        }
+
         /// 
         /// Handling method when the property with given name has changed.
         /// 
@@ -203,6 +211,9 @@ protected void OnPropertyChanged(string propertyName)
         /// 
         internal async Task ParseDocumentAsync()
         {
+            OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader());
+            OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader());
+
             Stream stream = null;
             try
             {
@@ -245,8 +256,9 @@ internal async Task ParseDocumentAsync()
                         settings.BaseUrl = new("file://" + Path.GetDirectoryName(_inputFile) + "/");
                     }
                 }
-                var readResult = await new OpenApiStreamReader(settings
-                ).ReadAsync(stream);
+
+                var format = OpenApiModelFactory.GetFormat(_inputFile);
+                var readResult = await OpenApiDocument.LoadAsync(stream, format);
                 var document = readResult.OpenApiDocument;
                 var context = readResult.OpenApiDiagnostic;
 
@@ -287,7 +299,8 @@ internal async Task ParseDocumentAsync()
                 Output = string.Empty;
                 Errors = "Failed to parse input: " + ex.Message;
             }
-            finally {
+            finally
+            {
                 if (stream != null)
                 {
                     stream.Close();
diff --git a/src/Microsoft.OpenApi.Workbench/MainWindow.xaml b/src/Microsoft.OpenApi.Workbench/MainWindow.xaml
index 41a4f2543..a3696f1e7 100644
--- a/src/Microsoft.OpenApi.Workbench/MainWindow.xaml
+++ b/src/Microsoft.OpenApi.Workbench/MainWindow.xaml
@@ -40,6 +40,7 @@
                     
                     
                         
+                        
                         
                         
                     
diff --git a/src/Microsoft.OpenApi.Workbench/MainWindow.xaml.cs b/src/Microsoft.OpenApi.Workbench/MainWindow.xaml.cs
index f9f1773c7..3c02c254d 100644
--- a/src/Microsoft.OpenApi.Workbench/MainWindow.xaml.cs
+++ b/src/Microsoft.OpenApi.Workbench/MainWindow.xaml.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
 using System;
diff --git a/src/Microsoft.OpenApi/Any/AnyType.cs b/src/Microsoft.OpenApi/Any/AnyType.cs
deleted file mode 100644
index 3ac617e8a..000000000
--- a/src/Microsoft.OpenApi/Any/AnyType.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Type of an 
-    /// 
-    public enum AnyType
-    {
-        /// 
-        /// Primitive.
-        /// 
-        Primitive,
-
-        /// 
-        /// Null.
-        /// 
-        Null,
-
-        /// 
-        /// Array.
-        /// 
-        Array,
-
-        /// 
-        /// Object.
-        /// 
-        Object
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/IOpenApiAny.cs b/src/Microsoft.OpenApi/Any/IOpenApiAny.cs
deleted file mode 100644
index ece675508..000000000
--- a/src/Microsoft.OpenApi/Any/IOpenApiAny.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Interfaces;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Base interface for all the types that represent Open API Any.
-    /// 
-    public interface IOpenApiAny : IOpenApiElement, IOpenApiExtension
-    {
-        /// 
-        /// Type of an .
-        /// 
-        AnyType AnyType { get; }
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/IOpenApiPrimitive.cs b/src/Microsoft.OpenApi/Any/IOpenApiPrimitive.cs
deleted file mode 100644
index 039782852..000000000
--- a/src/Microsoft.OpenApi/Any/IOpenApiPrimitive.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Primitive type.
-    /// 
-    public enum PrimitiveType
-    {
-        /// 
-        /// Integer
-        /// 
-        Integer,
-
-        /// 
-        /// Long
-        /// 
-        Long,
-
-        /// 
-        /// Float
-        /// 
-        Float,
-
-        /// 
-        /// Double
-        /// 
-        Double,
-
-        /// 
-        /// String
-        /// 
-        String,
-
-        /// 
-        /// Byte
-        /// 
-        Byte,
-
-        /// 
-        /// Binary
-        /// 
-        Binary,
-
-        /// 
-        /// Boolean
-        /// 
-        Boolean,
-
-        /// 
-        /// Date
-        /// 
-        Date,
-
-        /// 
-        /// DateTime
-        /// 
-        DateTime,
-
-        /// 
-        /// Password
-        /// 
-        Password
-    }
-
-    /// 
-    /// Base interface for the Primitive type.
-    /// 
-    public interface IOpenApiPrimitive : IOpenApiAny
-    {
-        /// 
-        /// Primitive type.
-        /// 
-        PrimitiveType PrimitiveType { get; }
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiAny.cs b/src/Microsoft.OpenApi/Any/OpenApiAny.cs
new file mode 100644
index 000000000..54bddf326
--- /dev/null
+++ b/src/Microsoft.OpenApi/Any/OpenApiAny.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.Text.Json.Nodes;
+using Microsoft.OpenApi.Interfaces;
+using Microsoft.OpenApi.Writers;
+
+namespace Microsoft.OpenApi.Any
+{
+    /// 
+    /// A wrapper class for JsonNode
+    /// 
+    public class OpenApiAny : IOpenApiElement, IOpenApiExtension
+    {
+        private readonly JsonNode jsonNode;
+
+        /// 
+        /// Initializes the  class.
+        /// 
+        /// 
+        public OpenApiAny(JsonNode jsonNode)
+        {
+            this.jsonNode = jsonNode;
+        }
+
+        /// 
+        /// Gets the underlying JsonNode.
+        /// 
+        public JsonNode Node { get { return jsonNode; } }
+
+        /// 
+        /// Writes out the OpenApiAny type.
+        /// 
+        /// 
+        /// 
+        public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
+        {
+            writer.WriteAny(Node);
+        }
+    }
+}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiAnyCloneHelper.cs b/src/Microsoft.OpenApi/Any/OpenApiAnyCloneHelper.cs
deleted file mode 100644
index eaa1dac31..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiAnyCloneHelper.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using System.Diagnostics.CodeAnalysis;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Contains logic for cloning objects through copy constructors.
-    /// 
-    public class OpenApiAnyCloneHelper
-    {
-        /// 
-        /// Clones an instance of  object from the copy constructor
-        /// 
-        /// The object instance.
-        /// A clone copy or the object itself.
-        [Obsolete("Use native AoT-friendly generic overload of CloneFromCopyConstructor instead.")]
-        [RequiresUnreferencedCode("CloneFromCopyConstructor is not trim-compatible. Recommended to use native AoT-friendly type-specific overloads of CloneFromCopyConstructor instead.")]
-        public static IOpenApiAny CloneFromCopyConstructor(IOpenApiAny obj)
-        {
-            if (obj != null)
-            {
-                var t = obj.GetType();
-                foreach (var ci in t.GetConstructors())
-                {
-                    var pi = ci.GetParameters();
-                    if (pi.Length == 1 && pi[0].ParameterType == t)
-                    {
-                        return (IOpenApiAny)ci.Invoke(new object[] { obj });
-                    }
-                }
-            }
-
-            return obj;
-        }
-        
-        /// 
-        /// Clones an instance of  object from the copy constructor
-        /// 
-        /// The object instance.
-        /// A clone copy or the object itself.
-        public static T CloneFromCopyConstructor<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(T obj) where T : IOpenApiAny
-        {
-            if (obj != null)
-            {
-                foreach (var ci in typeof(T).GetConstructors())
-                {
-                    var pi = ci.GetParameters();
-                    if (pi.Length == 1 && pi[0].ParameterType == typeof(T))
-                    {
-                        return (T)ci.Invoke([obj]);
-                    }
-                }
-            }
-
-            return obj;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiArray.cs b/src/Microsoft.OpenApi/Any/OpenApiArray.cs
deleted file mode 100644
index 5a9af0fff..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiArray.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Writers;
-using System.Collections.Generic;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API array.
-    /// 
-    public class OpenApiArray : List, IOpenApiAny
-    {
-        /// 
-        /// The type of 
-        /// 
-        public AnyType AnyType { get; } = AnyType.Array;
-
-        /// 
-        /// Parameterless constructor
-        /// 
-        public OpenApiArray() { }
-
-        /// 
-        /// Initializes a copy of  object
-        /// 
-        public OpenApiArray(OpenApiArray array)
-        {
-            AnyType = array.AnyType;
-            foreach (var item in array)
-            {
-                Add(OpenApiAnyCloneHelper.CloneFromCopyConstructor(item));
-            }
-        }
-
-        /// 
-        /// Write out contents of OpenApiArray to passed writer
-        /// 
-        /// Instance of JSON or YAML writer.
-        /// Version of the OpenAPI specification that that will be output.
-        public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
-        {
-            writer.WriteStartArray();
-
-            foreach (var item in this)
-            {
-                writer.WriteAny(item);
-            }
-
-            writer.WriteEndArray();
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiBinary.cs b/src/Microsoft.OpenApi/Any/OpenApiBinary.cs
deleted file mode 100644
index 23fdbe4d6..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiBinary.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API binary.
-    /// 
-    public class OpenApiBinary : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        /// 
-        public OpenApiBinary(byte[] value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Binary;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiBoolean.cs b/src/Microsoft.OpenApi/Any/OpenApiBoolean.cs
deleted file mode 100644
index aef1a42f8..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiBoolean.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API boolean.
-    /// 
-    public class OpenApiBoolean : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        /// 
-        public OpenApiBoolean(bool value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Boolean;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiByte.cs b/src/Microsoft.OpenApi/Any/OpenApiByte.cs
deleted file mode 100644
index f28a50175..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiByte.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API Byte
-    /// 
-    public class OpenApiByte : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiByte(byte value)
-            : this(new[] { value })
-        {
-        }
-
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiByte(byte[] value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Byte;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiDate.cs b/src/Microsoft.OpenApi/Any/OpenApiDate.cs
deleted file mode 100644
index 4552ddfc8..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiDate.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API Date
-    /// 
-    public class OpenApiDate : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiDate(DateTime value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Date;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiDateTime.cs b/src/Microsoft.OpenApi/Any/OpenApiDateTime.cs
deleted file mode 100644
index c812aa50c..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiDateTime.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API Datetime
-    /// 
-    public class OpenApiDateTime : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiDateTime(DateTimeOffset value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.DateTime;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiDouble.cs b/src/Microsoft.OpenApi/Any/OpenApiDouble.cs
deleted file mode 100644
index 3a913873c..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiDouble.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API Double
-    /// 
-    public class OpenApiDouble : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiDouble(double value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Double;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiFloat.cs b/src/Microsoft.OpenApi/Any/OpenApiFloat.cs
deleted file mode 100644
index 5e90a4106..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiFloat.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API Float
-    /// 
-    public class OpenApiFloat : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiFloat(float value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Float;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiInteger.cs b/src/Microsoft.OpenApi/Any/OpenApiInteger.cs
deleted file mode 100644
index fa47b4f48..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiInteger.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API Integer
-    /// 
-    public class OpenApiInteger : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiInteger(int value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Integer;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiLong.cs b/src/Microsoft.OpenApi/Any/OpenApiLong.cs
deleted file mode 100644
index f54b20084..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiLong.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API long.
-    /// 
-    public class OpenApiLong : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiLong(long value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// Primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Long;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiNull.cs b/src/Microsoft.OpenApi/Any/OpenApiNull.cs
deleted file mode 100644
index b606d98e1..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiNull.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Writers;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API null.
-    /// 
-    public class OpenApiNull : IOpenApiAny
-    {
-        /// 
-        /// The type of 
-        /// 
-        public AnyType AnyType { get; } = AnyType.Null;
-
-        /// 
-        /// Parameterless constructor
-        /// 
-        public OpenApiNull() { }
-
-        /// 
-        /// Initializes a copy of  object
-        /// 
-        public OpenApiNull(OpenApiNull openApiNull)
-        {
-            AnyType = openApiNull.AnyType;
-        }
-
-        /// 
-        /// Write out null representation
-        /// 
-        /// 
-        /// Version of the OpenAPI specification that that will be output.
-        public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
-        {
-            writer.WriteAny(this);
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiObject.cs b/src/Microsoft.OpenApi/Any/OpenApiObject.cs
deleted file mode 100644
index 95783cc23..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiObject.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System.Collections.Generic;
-using Microsoft.OpenApi.Writers;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API object.
-    /// 
-    public class OpenApiObject : Dictionary, IOpenApiAny
-    {
-        /// 
-        /// Type of .
-        /// 
-        public AnyType AnyType { get; } = AnyType.Object;
-
-        /// 
-        /// Parameterless constructor
-        /// 
-        public OpenApiObject() { }
-
-        /// 
-        /// Initializes a copy of  object
-        /// 
-        public OpenApiObject(OpenApiObject obj)
-        {
-            AnyType = obj.AnyType;
-            foreach (var key in obj.Keys)
-            {
-                this[key] = OpenApiAnyCloneHelper.CloneFromCopyConstructor(obj[key]);
-            }
-        }
-
-        /// 
-        /// Serialize OpenApiObject to writer
-        /// 
-        /// 
-        /// Version of the OpenAPI specification that that will be output.
-        public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
-        {
-            writer.WriteStartObject();
-
-            foreach (var item in this)
-            {
-                writer.WritePropertyName(item.Key);
-                writer.WriteAny(item.Value);
-            }
-
-            writer.WriteEndObject();
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiPassword.cs b/src/Microsoft.OpenApi/Any/OpenApiPassword.cs
deleted file mode 100644
index f9e68bf66..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiPassword.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API password.
-    /// 
-    public class OpenApiPassword : OpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class.
-        /// 
-        public OpenApiPassword(string value)
-            : base(value)
-        {
-        }
-
-        /// 
-        /// The primitive type this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.Password;
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiPrimitive.cs b/src/Microsoft.OpenApi/Any/OpenApiPrimitive.cs
deleted file mode 100644
index 3ac1b0082..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiPrimitive.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using System;
-using System.Globalization;
-using System.Text;
-using Microsoft.OpenApi.Exceptions;
-using Microsoft.OpenApi.Properties;
-using Microsoft.OpenApi.Writers;
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API primitive class.
-    /// 
-    /// 
-    public abstract class OpenApiPrimitive : IOpenApiPrimitive
-    {
-        /// 
-        /// Initializes the  class with the given value.
-        /// 
-        /// 
-        public OpenApiPrimitive(T value)
-        {
-            Value = value;
-        }
-
-        /// 
-        /// Initializes a copy of an  object
-        /// 
-        /// 
-        public OpenApiPrimitive(OpenApiPrimitive openApiPrimitive)
-        {
-            Value = openApiPrimitive.Value;
-        }
-
-        /// 
-        /// The kind of .
-        /// 
-        public AnyType AnyType => AnyType.Primitive;
-
-        /// 
-        /// The primitive class this object represents.
-        /// 
-        public abstract PrimitiveType PrimitiveType { get; }
-
-        /// 
-        /// Value of this 
-        /// 
-        public T Value { get; }
-
-        /// 
-        /// Write out content of primitive element
-        /// 
-        /// 
-        /// 
-        public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
-        {
-            switch (this.PrimitiveType)
-            {
-                case PrimitiveType.Integer:
-                    var intValue = (OpenApiInteger)(IOpenApiPrimitive)this;
-                    writer.WriteValue(intValue.Value);
-                    break;
-
-                case PrimitiveType.Long:
-                    var longValue = (OpenApiLong)(IOpenApiPrimitive)this;
-                    writer.WriteValue(longValue.Value);
-                    break;
-
-                case PrimitiveType.Float:
-                    var floatValue = (OpenApiFloat)(IOpenApiPrimitive)this;
-                    writer.WriteValue(floatValue.Value);
-                    break;
-
-                case PrimitiveType.Double:
-                    var doubleValue = (OpenApiDouble)(IOpenApiPrimitive)this;
-                    var actualValue = doubleValue.Value;
-                    if (actualValue.Equals(double.NaN)
-                        || actualValue.Equals(double.NegativeInfinity)
-                        || actualValue.Equals(double.PositiveInfinity))
-                    {
-                        // Write out NaN, -Infinity, Infinity as strings
-                        writer.WriteValue(actualValue.ToString(CultureInfo.InvariantCulture));
-                        break;
-                    }
-                    else
-                    {
-                        writer.WriteValue(actualValue);
-                    }
-                    break;
-
-                case PrimitiveType.String:
-                    var stringValue = (OpenApiString)(IOpenApiPrimitive)this;
-                    if (stringValue.IsRawString())
-                        writer.WriteRaw(stringValue.Value);
-                    else
-                        writer.WriteValue(stringValue.Value);
-                    break;
-
-                case PrimitiveType.Byte:
-                    var byteValue = (OpenApiByte)(IOpenApiPrimitive)this;
-                    if (byteValue.Value == null)
-                    {
-                        writer.WriteNull();
-                    }
-                    else
-                    {
-                        writer.WriteValue(Convert.ToBase64String(byteValue.Value));
-                    }
-
-                    break;
-
-                case PrimitiveType.Binary:
-                    var binaryValue = (OpenApiBinary)(IOpenApiPrimitive)this;
-                    if (binaryValue.Value == null)
-                    {
-                        writer.WriteNull();
-                    }
-                    else
-                    {
-                        writer.WriteValue(Encoding.UTF8.GetString(binaryValue.Value));
-                    }
-
-                    break;
-
-                case PrimitiveType.Boolean:
-                    var boolValue = (OpenApiBoolean)(IOpenApiPrimitive)this;
-                    writer.WriteValue(boolValue.Value);
-                    break;
-
-                case PrimitiveType.Date:
-                    var dateValue = (OpenApiDate)(IOpenApiPrimitive)this;
-                    writer.WriteValue(dateValue.Value.ToString("o").Substring(0, 10));
-                    break;
-
-                case PrimitiveType.DateTime:
-                    var dateTimeValue = (OpenApiDateTime)(IOpenApiPrimitive)this;
-                    writer.WriteValue(dateTimeValue.Value);
-                    break;
-
-                case PrimitiveType.Password:
-                    var passwordValue = (OpenApiPassword)(IOpenApiPrimitive)this;
-                    writer.WriteValue(passwordValue.Value);
-                    break;
-
-                default:
-                    throw new OpenApiWriterException(
-                        string.Format(
-                            SRResource.PrimitiveTypeNotSupported,
-                            this.PrimitiveType));
-            }
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi/Any/OpenApiString.cs b/src/Microsoft.OpenApi/Any/OpenApiString.cs
deleted file mode 100644
index fa1b799ee..000000000
--- a/src/Microsoft.OpenApi/Any/OpenApiString.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Microsoft.OpenApi.Any
-{
-    /// 
-    /// Open API string type.
-    /// 
-    public class OpenApiString : OpenApiPrimitive
-    {
-        private bool isExplicit;
-        private bool isRawString;
-
-        /// 
-        /// Initializes the  class.
-        /// 
-        /// 
-        public OpenApiString(string value)
-            : this(value, false)
-        {
-        }
-
-        /// 
-        /// Initializes the  class.
-        /// 
-        /// 
-        /// Used to indicate if a string is quoted.
-        public OpenApiString(string value, bool isExplicit)
-            : base(value)
-        {
-            this.isExplicit = isExplicit;
-        }
-
-        /// 
-        /// Initializes the  class.
-        /// 
-        /// 
-        /// Used to indicate if a string is quoted.
-        /// Used to indicate to the writer that the value should be written without encoding.
-        public OpenApiString(string value, bool isExplicit, bool isRawString)
-            : base(value)
-        {
-            this.isExplicit = isExplicit;
-            this.isRawString = isRawString;
-        }
-
-        /// 
-        /// The primitive class this object represents.
-        /// 
-        public override PrimitiveType PrimitiveType => PrimitiveType.String;
-
-        /// 
-        /// True if string was specified explicitly by the means of double quotes, single quotes, or literal or folded style.
-        /// 
-        public bool IsExplicit()
-        {
-            return this.isExplicit;
-        }
-
-        /// 
-        /// True if the writer should process the value as supplied without encoding.
-        /// 
-        public bool IsRawString()
-        {
-            return this.isRawString;
-        }
-    }
-}
diff --git a/src/Microsoft.OpenApi.Readers/Exceptions/OpenApiReaderException.cs b/src/Microsoft.OpenApi/Exceptions/OpenApiReaderException.cs
similarity index 87%
rename from src/Microsoft.OpenApi.Readers/Exceptions/OpenApiReaderException.cs
rename to src/Microsoft.OpenApi/Exceptions/OpenApiReaderException.cs
index 53ae62d50..257b0e9a4 100644
--- a/src/Microsoft.OpenApi.Readers/Exceptions/OpenApiReaderException.cs
+++ b/src/Microsoft.OpenApi/Exceptions/OpenApiReaderException.cs
@@ -1,11 +1,11 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
 using System;
-using Microsoft.OpenApi.Exceptions;
-using SharpYaml.Serialization;
+using System.Text.Json.Nodes;
+using Microsoft.OpenApi.Reader;
 
-namespace Microsoft.OpenApi.Readers.Exceptions
+namespace Microsoft.OpenApi.Exceptions
 {
     /// 
     /// Defines an exception indicating OpenAPI Reader encountered an issue while reading.
@@ -29,7 +29,8 @@ public OpenApiReaderException(string message) : base(message) { }
         /// 
         /// Plain text error message for this exception.
         /// Context of current parsing process.
-        public OpenApiReaderException(string message, ParsingContext context) : base(message) {
+        public OpenApiReaderException(string message, ParsingContext context) : base(message)
+        {
             Pointer = context.GetLocation();
         }
 
@@ -38,11 +39,10 @@ public OpenApiReaderException(string message, ParsingContext context) : base(mes
         /// 
         /// Plain text error message for this exception.
         /// Parsing node where error occured
-        public OpenApiReaderException(string message, YamlNode node) : base(message)
+        public OpenApiReaderException(string message, JsonNode node) : base(message)
         {
             // This only includes line because using a char range causes tests to break due to CR/LF & LF differences
             // See https://tools.ietf.org/html/rfc5147 for syntax
-            Pointer = $"#line={node.Start.Line}";
         }
 
         /// 
diff --git a/src/Microsoft.OpenApi.Readers/Exceptions/OpenApiUnsupportedSpecVersionException.cs b/src/Microsoft.OpenApi/Exceptions/OpenApiUnsupportedSpecVersionException.cs
similarity index 97%
rename from src/Microsoft.OpenApi.Readers/Exceptions/OpenApiUnsupportedSpecVersionException.cs
rename to src/Microsoft.OpenApi/Exceptions/OpenApiUnsupportedSpecVersionException.cs
index 2d125c259..f9be8bd63 100644
--- a/src/Microsoft.OpenApi.Readers/Exceptions/OpenApiUnsupportedSpecVersionException.cs
+++ b/src/Microsoft.OpenApi/Exceptions/OpenApiUnsupportedSpecVersionException.cs
@@ -4,7 +4,7 @@
 using System;
 using System.Globalization;
 
-namespace Microsoft.OpenApi.Readers.Exceptions
+namespace Microsoft.OpenApi.Exceptions
 {
     /// 
     /// Defines an exception indicating OpenAPI Reader encountered an unsupported specification version while reading.
diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiElementExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiElementExtensions.cs
index 38a53ecec..d0b0d9c35 100644
--- a/src/Microsoft.OpenApi/Extensions/OpenApiElementExtensions.cs
+++ b/src/Microsoft.OpenApi/Extensions/OpenApiElementExtensions.cs
@@ -24,6 +24,12 @@ public static class OpenApiElementExtensions
         public static IEnumerable Validate(this IOpenApiElement element, ValidationRuleSet ruleSet)
         {
             var validator = new OpenApiValidator(ruleSet);
+
+            if (element is OpenApiDocument doc)
+            {
+                validator.HostDocument = doc;
+            }
+            
             var walker = new OpenApiWalker(validator);
             walker.Walk(element);
             return validator.Errors.Cast().Union(validator.Warnings);
diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs
index 5fb1190eb..aca76f979 100644
--- a/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs
+++ b/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs
@@ -59,8 +59,6 @@ private static IOpenApiReferenceable ResolveReferenceOnHeaderElement(
         {
             switch (propertyName)
             {
-                case OpenApiConstants.Schema:
-                    return headerElement.Schema;
                 case OpenApiConstants.Examples when mapKey != null:
                     return headerElement.Examples[mapKey];
                 default:
@@ -76,8 +74,6 @@ private static IOpenApiReferenceable ResolveReferenceOnParameterElement(
         {
             switch (propertyName)
             {
-                case OpenApiConstants.Schema:
-                    return parameterElement.Schema;
                 case OpenApiConstants.Examples when mapKey != null:
                     return parameterElement.Examples[mapKey];
                 default:
diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs
index 845f6ce65..5d59a8de2 100755
--- a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs
+++ b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
 using System.Globalization;
@@ -106,6 +106,10 @@ public static void Serialize(this T element, IOpenApiWriter writer, OpenApiSp
 
             switch (specVersion)
             {
+                case OpenApiSpecVersion.OpenApi3_1:
+                    element.SerializeAsV31(writer);
+                    break;
+
                 case OpenApiSpecVersion.OpenApi3_0:
                     element.SerializeAsV3(writer);
                     break;
diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs
index 6b7801541..e6dadd44d 100644
--- a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs
+++ b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs
@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using Microsoft.OpenApi.Exceptions;
 using Microsoft.OpenApi.Models;
 
 namespace Microsoft.OpenApi.Extensions
@@ -12,40 +13,81 @@ namespace Microsoft.OpenApi.Extensions
     /// 
     public static class OpenApiTypeMapper
     {
+        /// 
+        /// Maps a JsonSchema data type to an identifier.
+        /// 
+        /// 
+        /// 
+        public static string ToIdentifier(this JsonSchemaType? schemaType)
+        {
+            return schemaType switch
+            {
+                JsonSchemaType.Null => "null",
+                JsonSchemaType.Boolean => "boolean",
+                JsonSchemaType.Integer => "integer",
+                JsonSchemaType.Number => "number",
+                JsonSchemaType.String => "string",
+                JsonSchemaType.Array => "array",
+                JsonSchemaType.Object => "object",
+                _ => null,
+            };
+        }
+
+        /// 
+        /// Converts a schema type's identifier into the enum equivalent
+        /// 
+        /// 
+        /// 
+        public static JsonSchemaType ToJsonSchemaType(this string identifier)
+        {
+            return identifier switch
+            {
+                "null" => JsonSchemaType.Null,
+                "boolean" => JsonSchemaType.Boolean,
+                "integer" or "int" => JsonSchemaType.Integer,
+                "number" or "double" or "float" or "decimal"=> JsonSchemaType.Number,
+                "string" => JsonSchemaType.String,
+                "array" => JsonSchemaType.Array,
+                "object" => JsonSchemaType.Object,
+                "file" => JsonSchemaType.String, // File is treated as string
+                _ => throw new OpenApiException(string.Format("Invalid schema type identifier: {0}", identifier))
+            };
+        }
+
         private static readonly Dictionary> _simpleTypeToOpenApiSchema = new()
         {
-            [typeof(bool)] = () => new() { Type = "boolean" },
-            [typeof(byte)] = () => new() { Type = "string", Format = "byte" },
-            [typeof(int)] = () => new() { Type = "number", Format = "int32" },
-            [typeof(uint)] = () => new() { Type = "number", Format = "int32" },
-            [typeof(long)] = () => new() { Type = "number", Format = "int64" },
-            [typeof(ulong)] = () => new() { Type = "number", Format = "int64" },
-            [typeof(float)] = () => new() { Type = "number", Format = "float" },
-            [typeof(double)] = () => new() { Type = "number", Format = "double" },
-            [typeof(decimal)] = () => new() { Type = "number", Format = "double" },
-            [typeof(DateTime)] = () => new() { Type = "string", Format = "date-time" },
-            [typeof(DateTimeOffset)] = () => new() { Type = "string", Format = "date-time" },
-            [typeof(Guid)] = () => new() { Type = "string", Format = "uuid" },
-            [typeof(char)] = () => new() { Type = "string" },
+            [typeof(bool)] = () => new() { Type = JsonSchemaType.Boolean },
+            [typeof(byte)] = () => new() { Type = JsonSchemaType.String, Format = "byte" },
+            [typeof(int)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32" },
+            [typeof(uint)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32" },
+            [typeof(long)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64" },
+            [typeof(ulong)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64" },
+            [typeof(float)] = () => new() { Type = JsonSchemaType.Number, Format = "float" },
+            [typeof(double)] = () => new() { Type = JsonSchemaType.Number, Format = "double" },
+            [typeof(decimal)] = () => new() { Type = JsonSchemaType.Number, Format = "double" },
+            [typeof(DateTime)] = () => new() { Type = JsonSchemaType.String, Format = "date-time" },
+            [typeof(DateTimeOffset)] = () => new() { Type = JsonSchemaType.String, Format = "date-time" },
+            [typeof(Guid)] = () => new() { Type = JsonSchemaType.String, Format = "uuid" },
+            [typeof(char)] = () => new() { Type = JsonSchemaType.String },
 
             // Nullable types
-            [typeof(bool?)] = () => new() { Type = "boolean", Nullable = true },
-            [typeof(byte?)] = () => new() { Type = "string", Format = "byte", Nullable = true },
-            [typeof(int?)] = () => new() { Type = "number", Format = "int32", Nullable = true },
-            [typeof(uint?)] = () => new() { Type = "number", Format = "int32", Nullable = true },
-            [typeof(long?)] = () => new() { Type = "number", Format = "int64", Nullable = true },
-            [typeof(ulong?)] = () => new() { Type = "number", Format = "int64", Nullable = true },
-            [typeof(float?)] = () => new() { Type = "number", Format = "float", Nullable = true },
-            [typeof(double?)] = () => new() { Type = "number", Format = "double", Nullable = true },
-            [typeof(decimal?)] = () => new() { Type = "number", Format = "double", Nullable = true },
-            [typeof(DateTime?)] = () => new() { Type = "string", Format = "date-time", Nullable = true },
-            [typeof(DateTimeOffset?)] = () => new() { Type = "string", Format = "date-time", Nullable = true },
-            [typeof(Guid?)] = () => new() { Type = "string", Format = "uuid", Nullable = true },
-            [typeof(char?)] = () => new() { Type = "string", Nullable = true },
+            [typeof(bool?)] = () => new() { Type = JsonSchemaType.Boolean, Nullable = true },
+            [typeof(byte?)] = () => new() { Type = JsonSchemaType.String, Format = "byte", Nullable = true },
+            [typeof(int?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true },
+            [typeof(uint?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true },
+            [typeof(long?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true },
+            [typeof(ulong?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true },
+            [typeof(float?)] = () => new() { Type = JsonSchemaType.Number, Format = "float", Nullable = true },
+            [typeof(double?)] = () => new() { Type = JsonSchemaType.Number, Format = "double", Nullable = true },
+            [typeof(decimal?)] = () => new() { Type = JsonSchemaType.Number, Format = "double", Nullable = true },
+            [typeof(DateTime?)] = () => new() { Type = JsonSchemaType.String, Format = "date-time", Nullable = true },
+            [typeof(DateTimeOffset?)] = () => new() { Type = JsonSchemaType.String, Format = "date-time", Nullable = true },
+            [typeof(Guid?)] = () => new() { Type = JsonSchemaType.String, Format = "uuid", Nullable = true },
+            [typeof(char?)] = () => new() { Type = JsonSchemaType.String, Nullable = true },
 
-            [typeof(Uri)] = () => new() { Type = "string", Format = "uri"}, // Uri is treated as simple string
-            [typeof(string)] = () => new() { Type = "string" },
-            [typeof(object)] = () => new() { Type = "object" }
+            [typeof(Uri)] = () => new() { Type = JsonSchemaType.String, Format = "uri" }, // Uri is treated as simple string
+            [typeof(string)] = () => new() { Type = JsonSchemaType.String },
+            [typeof(object)] = () => new() { Type = JsonSchemaType.Object }
         };
 
         /// 
@@ -79,11 +121,11 @@ public static OpenApiSchema MapTypeToOpenApiPrimitiveType(this Type type)
 
             return _simpleTypeToOpenApiSchema.TryGetValue(type, out var result)
                 ? result()
-                : new() { Type = "string" };
+                : new() { Type = JsonSchemaType.String };
         }
 
         /// 
-        /// Maps an OpenAPI data type and format to a simple type.
+        /// Maps an JsonSchema data type and format to a simple type.
         /// 
         /// The OpenApi data type
         /// The simple type
@@ -95,13 +137,13 @@ public static Type MapOpenApiPrimitiveTypeToSimpleType(this OpenApiSchema schema
                 throw new ArgumentNullException(nameof(schema));
             }
 
-            var type = (schema.Type?.ToLowerInvariant(), schema.Format?.ToLowerInvariant(), schema.Nullable) switch
+            var type = (schema.Type.ToIdentifier(), schema.Format?.ToLowerInvariant(), schema.Nullable) switch
             {
                 ("boolean", null, false) => typeof(bool),
                 // integer is technically not valid with format, but we must provide some compatibility
                 ("integer" or "number", "int32", false) => typeof(int),
                 ("integer" or "number", "int64", false) => typeof(long),
-                ("integer", null, false) => typeof(int),
+                ("integer", null, false) => typeof(long),
                 ("number", "float", false) => typeof(float),
                 ("number", "double", false) => typeof(double),
                 ("number", "decimal", false) => typeof(decimal),
@@ -116,7 +158,7 @@ public static Type MapOpenApiPrimitiveTypeToSimpleType(this OpenApiSchema schema
                 ("string", "uri", false) => typeof(Uri),
                 ("integer" or "number", "int32", true) => typeof(int?),
                 ("integer" or "number", "int64", true) => typeof(long?),
-                ("integer", null, true) => typeof(int?),
+                ("integer", null, true) => typeof(long?),
                 ("number", "float", true) => typeof(float?),
                 ("number", "double", true) => typeof(double?),
                 ("number", null, true) => typeof(double?),
diff --git a/src/Microsoft.OpenApi/Helpers/JsonNodeCloneHelper.cs b/src/Microsoft.OpenApi/Helpers/JsonNodeCloneHelper.cs
new file mode 100644
index 000000000..d6e9cb9df
--- /dev/null
+++ b/src/Microsoft.OpenApi/Helpers/JsonNodeCloneHelper.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using System.Text.Json.Serialization;
+using Microsoft.OpenApi.Any;
+
+namespace Microsoft.OpenApi.Helpers
+{
+    internal static class JsonNodeCloneHelper
+    {
+        private static readonly JsonSerializerOptions options = new()
+        {
+            ReferenceHandler = ReferenceHandler.IgnoreCycles
+        };
+
+        internal static JsonNode Clone(JsonNode value)
+        {
+            var jsonString = Serialize(value);
+            if (string.IsNullOrEmpty(jsonString))
+            {
+                return null;
+            }
+
+            var result = JsonSerializer.Deserialize(jsonString, options);
+            return result;
+        }
+
+        private static string Serialize(object obj)
+        {
+            if (obj == null)
+            {
+                return null;
+            }
+            var result = JsonSerializer.Serialize(obj, options);
+            return result;
+        }
+    }
+}
diff --git a/src/Microsoft.OpenApi.Readers/Interface/IDiagnostic.cs b/src/Microsoft.OpenApi/Interfaces/IDiagnostic.cs
similarity index 85%
rename from src/Microsoft.OpenApi.Readers/Interface/IDiagnostic.cs
rename to src/Microsoft.OpenApi/Interfaces/IDiagnostic.cs
index 65511ce11..74376de02 100644
--- a/src/Microsoft.OpenApi.Readers/Interface/IDiagnostic.cs
+++ b/src/Microsoft.OpenApi/Interfaces/IDiagnostic.cs
@@ -1,7 +1,7 @@
 // Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
-namespace Microsoft.OpenApi.Readers.Interface
+namespace Microsoft.OpenApi.Interfaces
 {
     /// 
     /// Interface for the entity containing diagnostic information from the reading process.
diff --git a/src/Microsoft.OpenApi/Interfaces/IEffective.cs b/src/Microsoft.OpenApi/Interfaces/IEffective.cs
deleted file mode 100644
index b3ac0a37b..000000000
--- a/src/Microsoft.OpenApi/Interfaces/IEffective.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-using Microsoft.OpenApi.Models;
-
-namespace Microsoft.OpenApi.Interfaces
-{
-    /// 
-    /// OpenApiElements that implement IEffective indicate that their description is not self-contained.
-    /// External elements affect the effective description.
-    /// 
-    /// Currently this will only be used for accessing external references.
-    /// In the next major version, this will be the approach accessing all referenced elements.
-    /// This will enable us to support merging properties that are peers of the $ref  
-    /// Type of OpenApi Element that is being referenced.
-    public interface IEffective  where T : class,IOpenApiElement
-    {
-        /// 
-        /// Returns a calculated and cloned version of the element.
-        /// 
-        T GetEffective(OpenApiDocument document);
-    }
-}
diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs
new file mode 100644
index 000000000..5f8b1cb22
--- /dev/null
+++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. 
+
+using System.IO;
+using System.Text.Json.Nodes;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.OpenApi.Reader;
+
+namespace Microsoft.OpenApi.Interfaces
+{
+    /// 
+    /// Interface for Open API readers.
+    /// 
+    public interface IOpenApiReader
+    {
+        /// 
+        /// Reads the TextReader input and parses it into an Open API document.
+        /// 
+        /// The TextReader input.
+        ///  The OpenApi reader settings.
+        /// Propagates notification that an operation should be cancelled.
+        /// 
+        Task ReadAsync(TextReader input, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default);
+
+        /// 
+        /// Parses the JsonNode input into an Open API document.
+        /// 
+        /// The JsonNode input.
+        /// The Reader settings to be used during parsing.
+        /// Propagates notifications that operations should be cancelled.
+        /// The OpenAPI format.
+        /// 
+        Task ReadAsync(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null, CancellationToken cancellationToken = default);
+
+        /// 
+        /// Reads the TextReader input and parses the fragment of an OpenAPI description into an Open API Element.
+        /// 
+        /// TextReader containing OpenAPI description to parse.
+        /// Version of the OpenAPI specification that the fragment conforms to.
+        /// Returns diagnostic object containing errors detected during parsing.
+        /// The OpenApiReader settings.
+        /// Instance of newly created IOpenApiElement.
+        T ReadFragment(TextReader input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement;
+
+        /// 
+        /// Reads the JsonNode input and parses the fragment of an OpenAPI description into an Open API Element.
+        /// 
+        /// TextReader containing OpenAPI description to parse.
+        /// Version of the OpenAPI specification that the fragment conforms to.
+        /// Returns diagnostic object containing errors detected during parsing.
+        /// The OpenApiReader settings.
+        /// Instance of newly created IOpenApiElement.
+        T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement;
+    }
+}
diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs
index 39d345319..0920fb1ef 100644
--- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs
+++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceable.cs
@@ -20,16 +20,5 @@ public interface IOpenApiReferenceable : IOpenApiSerializable
         /// Reference object.
         /// 
         OpenApiReference Reference { get; set; }
-
-        /// 
-        /// Serialize to OpenAPI V3 document without using reference.
-        /// 
-        void SerializeAsV3WithoutReference(IOpenApiWriter writer);
-
-        /// 
-        /// Serialize to OpenAPI V2 document without using reference.
-        /// 
-        void SerializeAsV2WithoutReference(IOpenApiWriter writer);
-
     }
 }
diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs
index a3b22bd08..081545b14 100644
--- a/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs
+++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs
@@ -10,6 +10,12 @@ namespace Microsoft.OpenApi.Interfaces
     /// 
     public interface IOpenApiSerializable : IOpenApiElement
     {
+        /// 
+        /// Serialize OpenAPI element into v3.1
+        /// 
+        /// 
+        void SerializeAsV31(IOpenApiWriter writer);
+
         /// 
         /// Serialize Open API element to v3.0.
         /// 
diff --git a/src/Microsoft.OpenApi.Readers/Interface/IOpenApiVersionService.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiVersionService.cs
similarity index 58%
rename from src/Microsoft.OpenApi.Readers/Interface/IOpenApiVersionService.cs
rename to src/Microsoft.OpenApi/Interfaces/IOpenApiVersionService.cs
index d70766132..97d1d3c9b 100644
--- a/src/Microsoft.OpenApi.Readers/Interface/IOpenApiVersionService.cs
+++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiVersionService.cs
@@ -1,11 +1,10 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
-using Microsoft.OpenApi.Interfaces;
 using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Readers.ParseNodes;
+using Microsoft.OpenApi.Reader.ParseNodes;
 
-namespace Microsoft.OpenApi.Readers.Interface
+namespace Microsoft.OpenApi.Interfaces
 {
     /// 
     /// Interface to a version specific parsing implementations.
@@ -17,16 +16,19 @@ internal interface IOpenApiVersionService
         /// 
         /// The reference string.
         /// The type of the reference.
+        /// The summary of the reference.
+        /// A reference description
         /// The  object or null.
-        OpenApiReference ConvertToOpenApiReference(string reference, ReferenceType? type);
+        OpenApiReference ConvertToOpenApiReference(string reference, ReferenceType? type, string summary = null, string description = null);
 
         /// 
         /// Loads an OpenAPI Element from a document fragment
         /// 
         /// Type of element to load
         /// document fragment node
+        /// A host document instance.
         /// Instance of OpenAPIElement
-        T LoadElement(ParseNode node) where T : IOpenApiElement;
+        T LoadElement(ParseNode node, OpenApiDocument doc = null) where T : IOpenApiElement;
 
         /// 
         /// Converts a generic RootNode instance into a strongly typed OpenApiDocument
@@ -34,5 +36,13 @@ internal interface IOpenApiVersionService
         /// RootNode containing the information to be converted into an OpenAPI Document
         /// Instance of OpenApiDocument populated with data from rootNode
         OpenApiDocument LoadDocument(RootNode rootNode);
+
+        /// 
+        /// Gets the description and summary scalar values in a reference object for V3.1 support
+        /// 
+        /// A YamlMappingNode.
+        /// The scalar value we're parsing.
+        /// The resulting node value.
+        string GetReferenceScalarValues(MapNode mapNode, string scalarValue);
     }
 }
diff --git a/src/Microsoft.OpenApi.Readers/Interface/IStreamLoader.cs b/src/Microsoft.OpenApi/Interfaces/IStreamLoader.cs
similarity index 95%
rename from src/Microsoft.OpenApi.Readers/Interface/IStreamLoader.cs
rename to src/Microsoft.OpenApi/Interfaces/IStreamLoader.cs
index 1c5471238..c3edebe1b 100644
--- a/src/Microsoft.OpenApi.Readers/Interface/IStreamLoader.cs
+++ b/src/Microsoft.OpenApi/Interfaces/IStreamLoader.cs
@@ -7,7 +7,7 @@
 using System.Threading.Tasks;
 using Microsoft.OpenApi.Models;
 
-namespace Microsoft.OpenApi.Readers.Interface
+namespace Microsoft.OpenApi.Interfaces
 {
     /// 
     /// Interface for service that translates a URI into a stream that can be loaded by a Reader
diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
index eb0ee6b12..6ddac0ec9 100644
--- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
+++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
@@ -3,7 +3,7 @@
         netstandard2.0
         Latest
         true
-        1.6.22
+        2.0.0-preview1
         .NET models with JSON and YAML writers for OpenAPI specification
         true
         
@@ -17,6 +17,14 @@
         ..\Microsoft.OpenApi.snk
     
 
+    
+    
+        true
+    
+            
+        
+    
+
     
         
             True
diff --git a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiDeprecationExtension.cs b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiDeprecationExtension.cs
index 683082e2c..a5bae9fa9 100644
--- a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiDeprecationExtension.cs
+++ b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiDeprecationExtension.cs
@@ -8,6 +8,7 @@
 using Microsoft.OpenApi.Any;
 using Microsoft.OpenApi.Interfaces;
 using Microsoft.OpenApi.Writers;
+using System.Text.Json.Nodes;
 
 namespace Microsoft.OpenApi.MicrosoftExtensions;
 
@@ -71,23 +72,23 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
         }
     }
     /// 
-    /// Parses the  to .
+    /// Parses the  to .
     /// 
     /// The source object.
     /// The .
     /// When the source element is not an object
-    public static OpenApiDeprecationExtension Parse(IOpenApiAny source)
+    public static OpenApiDeprecationExtension Parse(JsonNode source)
     {
-        if (source is not OpenApiObject rawObject) return null;
+        if (source is not JsonObject rawObject) return null;
         var extension = new OpenApiDeprecationExtension();
-        if (rawObject.TryGetValue(nameof(RemovalDate).ToFirstCharacterLowerCase(), out var removalDate) && removalDate is OpenApiDateTime removalDateValue)
-            extension.RemovalDate = removalDateValue.Value;
-        if (rawObject.TryGetValue(nameof(Date).ToFirstCharacterLowerCase(), out var date) && date is OpenApiDateTime dateValue)
-            extension.Date = dateValue.Value;
-        if (rawObject.TryGetValue(nameof(Version).ToFirstCharacterLowerCase(), out var version) && version is OpenApiString versionValue)
-            extension.Version = versionValue.Value;
-        if (rawObject.TryGetValue(nameof(Description).ToFirstCharacterLowerCase(), out var description) && description is OpenApiString descriptionValue)
-            extension.Description = descriptionValue.Value;
+        if (rawObject.TryGetPropertyValue(nameof(RemovalDate).ToFirstCharacterLowerCase(), out var removalDate) && removalDate is JsonNode removalDateValue)
+            extension.RemovalDate = removalDateValue.GetValue();
+        if (rawObject.TryGetPropertyValue(nameof(Date).ToFirstCharacterLowerCase(), out var date) && date is JsonNode dateValue)
+            extension.Date = dateValue.GetValue();
+        if (rawObject.TryGetPropertyValue(nameof(Version).ToFirstCharacterLowerCase(), out var version) && version is JsonNode versionValue)
+            extension.Version = versionValue.GetValue();
+        if (rawObject.TryGetPropertyValue(nameof(Description).ToFirstCharacterLowerCase(), out var description) && description is JsonNode descriptionValue)
+            extension.Description = descriptionValue.GetValue();
         return extension;
     }
 }
diff --git a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumFlagsExtension.cs b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumFlagsExtension.cs
index 946537478..9cbae6350 100644
--- a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumFlagsExtension.cs
+++ b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumFlagsExtension.cs
@@ -8,6 +8,7 @@
 using Microsoft.OpenApi.Any;
 using Microsoft.OpenApi.Interfaces;
 using Microsoft.OpenApi.Writers;
+using System.Text.Json.Nodes;
 
 namespace Microsoft.OpenApi.MicrosoftExtensions;
 
@@ -38,18 +39,18 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
         writer.WriteEndObject();
     }
     /// 
-    /// Parse the extension from the raw IOpenApiAny object.
+    /// Parse the extension from the raw OpenApiAny object.
     /// 
     /// The source element to parse.
     /// The .
     /// When the source element is not an object
-    public static OpenApiEnumFlagsExtension Parse(IOpenApiAny source)
+    public static OpenApiEnumFlagsExtension Parse(JsonNode source)
     {
-        if (source is not OpenApiObject rawObject) return null;
+        if (source is not JsonObject rawObject) throw new ArgumentOutOfRangeException(nameof(source));
         var extension = new OpenApiEnumFlagsExtension();
-        if (rawObject.TryGetValue(nameof(IsFlags).ToFirstCharacterLowerCase(), out var flagsValue) && flagsValue is OpenApiBoolean isFlags)
+        if (rawObject.TryGetPropertyValue(nameof(IsFlags).ToFirstCharacterLowerCase(), out var flagsValue) && flagsValue is JsonNode isFlags)
         {
-            extension.IsFlags = isFlags.Value;
+            extension.IsFlags = isFlags.GetValue();
         }
         return extension;
     }
diff --git a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumValuesDescriptionExtension.cs b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumValuesDescriptionExtension.cs
index 272f4b313..1235e68b0 100644
--- a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumValuesDescriptionExtension.cs
+++ b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiEnumValuesDescriptionExtension.cs
@@ -10,6 +10,7 @@
 using Microsoft.OpenApi.Any;
 using Microsoft.OpenApi.Interfaces;
 using Microsoft.OpenApi.Writers;
+using System.Text.Json.Nodes;
 
 namespace Microsoft.OpenApi.MicrosoftExtensions;
 
@@ -62,14 +63,14 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
     /// The source element to parse.
     /// The .
     /// When the source element is not an object
-    public static OpenApiEnumValuesDescriptionExtension Parse(IOpenApiAny source)
+    public static OpenApiEnumValuesDescriptionExtension Parse(JsonNode source)
     {
-        if (source is not OpenApiObject rawObject) return null;
+        if (source is not JsonObject rawObject) return null;
         var extension = new OpenApiEnumValuesDescriptionExtension();
-        if (rawObject.TryGetValue("values", out var values) && values is OpenApiArray valuesArray)
+        if (rawObject.TryGetPropertyValue("values", out var values) && values is JsonArray valuesArray)
         {
             extension.ValuesDescriptions.AddRange(valuesArray
-                                            .OfType()
+                                            .OfType()
                                             .Select(x => new EnumDescription(x)));
         }
         return extension;
@@ -92,15 +93,15 @@ public EnumDescription()
     /// Constructor from a raw OpenApiObject
     /// 
     /// The source object
-    public EnumDescription(OpenApiObject source)
+    public EnumDescription(JsonObject source)
     {
         if (source is null) throw new ArgumentNullException(nameof(source));
-        if (source.TryGetValue(nameof(Value).ToFirstCharacterLowerCase(), out var rawValue) && rawValue is OpenApiString value)
-            Value = value.Value;
-        if (source.TryGetValue(nameof(Description).ToFirstCharacterLowerCase(), out var rawDescription) && rawDescription is OpenApiString description)
-            Description = description.Value;
-        if (source.TryGetValue(nameof(Name).ToFirstCharacterLowerCase(), out var rawName) && rawName is OpenApiString name)
-            Name = name.Value;
+        if (source.TryGetPropertyValue(nameof(Value).ToFirstCharacterLowerCase(), out var rawValue) && rawValue is JsonNode value)
+            Value = value.GetValue();
+        if (source.TryGetPropertyValue(nameof(Description).ToFirstCharacterLowerCase(), out var rawDescription) && rawDescription is JsonNode description)
+            Description = description.GetValue();
+        if (source.TryGetPropertyValue(nameof(Name).ToFirstCharacterLowerCase(), out var rawName) && rawName is JsonNode name)
+            Name = name.GetValue();
     }
     /// 
     /// The description for the enum symbol
diff --git a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPagingExtension.cs b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPagingExtension.cs
index 9b81e2561..f64eebf3f 100644
--- a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPagingExtension.cs
+++ b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPagingExtension.cs
@@ -8,6 +8,7 @@
 using Microsoft.OpenApi.Any;
 using Microsoft.OpenApi.Interfaces;
 using Microsoft.OpenApi.Writers;
+using System.Text.Json.Nodes;
 
 namespace Microsoft.OpenApi.MicrosoftExtensions;
 
@@ -71,23 +72,23 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
     /// The source element to parse.
     /// The .
     /// When the source element is not an object
-    public static OpenApiPagingExtension Parse(IOpenApiAny source)
+    public static OpenApiPagingExtension Parse(JsonNode source)
     {
-        if (source is not OpenApiObject rawObject) return null;
+        if (source is not JsonObject rawObject) return null;
         var extension = new OpenApiPagingExtension();
-        if (rawObject.TryGetValue(nameof(NextLinkName).ToFirstCharacterLowerCase(), out var nextLinkName) && nextLinkName is OpenApiString nextLinkNameStr)
+        if (rawObject.TryGetPropertyValue(nameof(NextLinkName).ToFirstCharacterLowerCase(), out var nextLinkName) && nextLinkName is JsonNode nextLinkNameStr)
         {
-            extension.NextLinkName = nextLinkNameStr.Value;
+            extension.NextLinkName = nextLinkNameStr.GetValue();
         }
 
-        if (rawObject.TryGetValue(nameof(OperationName).ToFirstCharacterLowerCase(), out var opName) && opName is OpenApiString opNameStr)
+        if (rawObject.TryGetPropertyValue(nameof(OperationName).ToFirstCharacterLowerCase(), out var opName) && opName is JsonNode opNameStr)
         {
-            extension.OperationName = opNameStr.Value;
+            extension.OperationName = opNameStr.GetValue();
         }
 
-        if (rawObject.TryGetValue(nameof(ItemName).ToFirstCharacterLowerCase(), out var itemName) && itemName is OpenApiString itemNameStr)
+        if (rawObject.TryGetPropertyValue(nameof(ItemName).ToFirstCharacterLowerCase(), out var itemName) && itemName is JsonNode itemNameStr)
         {
-            extension.ItemName = itemNameStr.Value;
+            extension.ItemName = itemNameStr.GetValue();
         }
 
         return extension;
diff --git a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPrimaryErrorMessageExtension.cs b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPrimaryErrorMessageExtension.cs
index 0250af758..ad47db39b 100644
--- a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPrimaryErrorMessageExtension.cs
+++ b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiPrimaryErrorMessageExtension.cs
@@ -4,6 +4,7 @@
 // ------------------------------------------------------------
 
 using System;
+using System.Text.Json.Nodes;
 using Microsoft.OpenApi.Any;
 using Microsoft.OpenApi.Interfaces;
 using Microsoft.OpenApi.Writers;
@@ -33,16 +34,16 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
     public bool IsPrimaryErrorMessage { get; set; }
 
     /// 
-    /// Parses the  to .
+    /// Parses the  to .
     /// 
     /// The source object.
     /// The .
-    public static OpenApiPrimaryErrorMessageExtension Parse(IOpenApiAny source)
+    public static OpenApiPrimaryErrorMessageExtension Parse(JsonNode source)
     {
-        if (source is not OpenApiBoolean rawObject) return null;
+        if (source is not JsonNode rawObject) return null;
         return new()
         {
-            IsPrimaryErrorMessage = rawObject.Value
+            IsPrimaryErrorMessage = rawObject.GetValue()
         };
     }
 }
diff --git a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiReservedParameterExtension.cs b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiReservedParameterExtension.cs
index e45d9e7e9..2d3a8c117 100644
--- a/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiReservedParameterExtension.cs
+++ b/src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiReservedParameterExtension.cs
@@ -4,6 +4,7 @@
 // ------------------------------------------------------------
 
 using System;
+using System.Text.Json.Nodes;
 using Microsoft.OpenApi.Any;
 using Microsoft.OpenApi.Interfaces;
 using Microsoft.OpenApi.Writers;
@@ -34,17 +35,17 @@ public bool? IsReserved
         get; set;
     }
     /// 
-    /// Parses the  to .
+    /// Parses the  to .
     /// 
     /// The source object.
     /// The .
     /// 
-    public static OpenApiReservedParameterExtension Parse(IOpenApiAny source)
+    public static OpenApiReservedParameterExtension Parse(JsonNode source)
     {
-        if (source is not OpenApiBoolean rawBoolean) return null;
+        if (source is not JsonNode rawBoolean) return null;
         return new()
         {
-            IsReserved = rawBoolean.Value
+            IsReserved = rawBoolean.GetValue()
         };
     }
 }
diff --git a/src/Microsoft.OpenApi/Models/JsonSchemaType.cs b/src/Microsoft.OpenApi/Models/JsonSchemaType.cs
new file mode 100644
index 000000000..6024aa21b
--- /dev/null
+++ b/src/Microsoft.OpenApi/Models/JsonSchemaType.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+
+namespace Microsoft.OpenApi.Models
+{
+    /// 
+    /// Represents the type of a JSON schema.
+    /// 
+    [Flags]
+    public enum JsonSchemaType
+    {
+        /// 
+        /// Represents a null type.
+        /// 
+        Null = 1,
+
+        /// 
+        /// Represents a boolean type.
+        /// 
+        Boolean = 2,
+
+        /// 
+        /// Represents an integer type.
+        /// 
+        Integer = 4,
+
+        /// 
+        /// Represents a number type.
+        /// 
+        Number = 8,
+
+        /// 
+        /// Represents a string type.
+        /// 
+        String = 16,
+
+        /// 
+        /// Represents an object type.
+        /// 
+        Object = 32,
+
+        /// 
+        /// Represents an array type.
+        /// 
+        Array = 64,
+    }
+}
diff --git a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs
index 98799c9c6..f538d90c0 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs
@@ -1,6 +1,7 @@
 // Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
+using System;
 using System.Collections.Generic;
 using Microsoft.OpenApi.Expressions;
 using Microsoft.OpenApi.Interfaces;
@@ -11,18 +12,18 @@ namespace Microsoft.OpenApi.Models
     /// 
     /// Callback Object: A map of possible out-of band callbacks related to the parent operation.
     /// 
-    public class OpenApiCallback : IOpenApiReferenceable, IOpenApiExtensible, IEffective
+    public class OpenApiCallback : IOpenApiReferenceable, IOpenApiExtensible
     {
         /// 
         /// A Path Item Object used to define a callback request and expected responses.
         /// 
-        public Dictionary PathItems { get; set; }
+        public virtual Dictionary PathItems { get; set; }
             = new();
 
         /// 
         /// Indicates if object is populated with data or is just a reference to the data
         /// 
-        public bool UnresolvedReference { get; set; }
+        public virtual bool UnresolvedReference { get; set; }
 
         /// 
         /// Reference pointer.
@@ -32,7 +33,7 @@ public class OpenApiCallback : IOpenApiReferenceable, IOpenApiExtensible, IEffec
         /// 
         /// This object MAY be extended with Specification Extensions.
         /// 
-        public IDictionary Extensions { get; set; } = new Dictionary();
+        public virtual IDictionary Extensions { get; set; } = new Dictionary();
 
         /// 
         /// Parameter-less constructor
@@ -60,71 +61,44 @@ public void AddPathItem(RuntimeExpression expression, OpenApiPathItem pathItem)
             Utils.CheckArgumentNull(expression);
             Utils.CheckArgumentNull(pathItem);
 
-            if (PathItems == null)
-            {
-                PathItems = new();
-            }
+            PathItems ??= new();
 
             PathItems.Add(expression, pathItem);
         }
 
         /// 
-        /// Serialize  to Open Api v3.0
+        /// Serialize  to Open Api v3.1
         /// 
-        public void SerializeAsV3(IOpenApiWriter writer)
+        /// 
+        /// 
+        public virtual void SerializeAsV31(IOpenApiWriter writer)
         {
-            Utils.CheckArgumentNull(writer);
-
-            var target = this;
-
-            if (Reference != null)
-            {
-                if (!writer.GetSettings().ShouldInlineReference(Reference))
-                {
-                    Reference.SerializeAsV3(writer);
-                    return;
-                }
-                else
-                {
-                    target = GetEffective(Reference.HostDocument);
-                }
-            }
-            target.SerializeAsV3WithoutReference(writer);
+            SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer));
         }
 
         /// 
-        /// Returns an effective OpenApiCallback object based on the presence of a $ref
+        /// Serialize  to Open Api v3.0
         /// 
-        /// The host OpenApiDocument that contains the reference.
-        /// OpenApiCallback
-        public OpenApiCallback GetEffective(OpenApiDocument doc)
+        public virtual void SerializeAsV3(IOpenApiWriter writer)
         {
-            if (this.Reference != null)
-            {
-                return doc.ResolveReferenceTo(this.Reference);
-            }
-            else
-            {
-                return this;
-            }
+            SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer));
         }
 
-        /// 
-        /// Serialize to OpenAPI V3 document without using reference.
-        /// 
-
-        public void SerializeAsV3WithoutReference(IOpenApiWriter writer)
+        internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
+            Action callback)
         {
+            Utils.CheckArgumentNull(writer);
+
             writer.WriteStartObject();
 
             // path items
             foreach (var item in PathItems)
             {
-                writer.WriteRequiredObject(item.Key.Expression, item.Value, (w, p) => p.SerializeAsV3(w));
+                writer.WriteRequiredObject(item.Key.Expression, item.Value, callback);
             }
 
             // extensions
-            writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0);
+            writer.WriteExtensions(Extensions, version);
 
             writer.WriteEndObject();
         }
@@ -136,14 +110,5 @@ public void SerializeAsV2(IOpenApiWriter writer)
         {
             // Callback object does not exist in V2.
         }
-
-        /// 
-        /// Serialize to OpenAPI V2 document without using reference.
-        /// 
-
-        public void SerializeAsV2WithoutReference(IOpenApiWriter writer)
-        {
-            // Callback object does not exist in V2.
-        }
     }
 }
diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs
index 52e8cac14..f672b7dd1 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs
@@ -1,11 +1,15 @@
 // Copyright (c) Microsoft Corporation. All rights reserved.
 // Licensed under the MIT license.
 
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using Microsoft.OpenApi.Interfaces;
+using Microsoft.OpenApi.Models.References;
 using Microsoft.OpenApi.Writers;
 
+#nullable enable
+
 namespace Microsoft.OpenApi.Models
 {
     /// 
@@ -16,55 +20,60 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary Schemas { get; set; } = new Dictionary();
+        public IDictionary? Schemas { get; set; } = new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary Responses { get; set; } = new Dictionary();
+        public virtual IDictionary? Responses { get; set; } = new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary Parameters { get; set; } =
+        public virtual IDictionary? Parameters { get; set; } =
             new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary Examples { get; set; } = new Dictionary();
+        public virtual IDictionary? Examples { get; set; } = new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary RequestBodies { get; set; } =
+        public virtual IDictionary? RequestBodies { get; set; } =
             new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary Headers { get; set; } = new Dictionary();
+        public virtual IDictionary? Headers { get; set; } = new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary SecuritySchemes { get; set; } =
+        public virtual IDictionary? SecuritySchemes { get; set; } =
             new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary Links { get; set; } = new Dictionary();
+        public virtual IDictionary? Links { get; set; } = new Dictionary();
 
         /// 
         /// An object to hold reusable  Objects.
         /// 
-        public IDictionary Callbacks { get; set; } = new Dictionary();
+        public virtual IDictionary? Callbacks { get; set; } = new Dictionary();
+
+        /// 
+        /// An object to hold reusable  Object.
+        /// 
+        public virtual IDictionary? PathItems { get; set; } = new Dictionary();
 
         /// 
         /// This object MAY be extended with Specification Extensions.
         /// 
-        public IDictionary Extensions { get; set; } = new Dictionary();
+        public virtual IDictionary? Extensions { get; set; } = new Dictionary();
 
         /// 
         /// Parameter-less constructor
@@ -74,7 +83,7 @@ public OpenApiComponents() { }
         /// 
         /// Initializes a copy of an  object
         /// 
-        public OpenApiComponents(OpenApiComponents components)
+        public OpenApiComponents(OpenApiComponents? components)
         {
             Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null;
             Responses = components?.Responses != null ? new Dictionary(components.Responses) : null;
@@ -85,13 +94,15 @@ public OpenApiComponents(OpenApiComponents components)
             SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary(components.SecuritySchemes) : null;
             Links = components?.Links != null ? new Dictionary(components.Links) : null;
             Callbacks = components?.Callbacks != null ? new Dictionary(components.Callbacks) : null;
+            PathItems = components?.PathItems != null ? new Dictionary(components.PathItems) : null;
             Extensions = components?.Extensions != null ? new Dictionary(components.Extensions) : null;
         }
 
         /// 
-        /// Serialize  to Open Api v3.0.
+        /// Serialize  to Open API v3.1.
         /// 
-        public void SerializeAsV3(IOpenApiWriter writer)
+        /// 
+        public void SerializeAsV31(IOpenApiWriter writer)
         {
             Utils.CheckArgumentNull(writer);
 
@@ -99,24 +110,59 @@ public void SerializeAsV3(IOpenApiWriter writer)
             // however if they have cycles, then we will need a component rendered
             if (writer.GetSettings().InlineLocalReferences)
             {
-                var loops = writer.GetSettings().LoopDetector.Loops;
-                writer.WriteStartObject();
-                if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas))
-                {
-                    var openApiSchemas = schemas.Cast().Distinct().ToList()
-                        .ToDictionary(k => k.Reference.Id);
+                RenderComponents(writer, (writer, element) => element.SerializeAsV31(writer));
+                return;
+            }
+
+            writer.WriteStartObject();
 
-                    writer.WriteOptionalMap(
-                       OpenApiConstants.Schemas,
-                       Schemas,
-                       (w, _, component) => component.SerializeAsV3WithoutReference(w));
+            // pathItems - only present in v3.1
+            writer.WriteOptionalMap(
+            OpenApiConstants.PathItems,
+            PathItems,
+            (w, key, component) =>
+            {
+                if (component is OpenApiPathItemReference reference)
+                {
+                    reference.SerializeAsV31(w);
+                }
+                else
+                {
+                    component.SerializeAsV31(w);
                 }
-                writer.WriteEndObject();
+            });
+
+            SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer),
+               (writer, referenceElement) => referenceElement.SerializeAsV31(writer));
+        }
+
+        /// 
+        /// Serialize  to v3.0
+        /// 
+        /// 
+        public void SerializeAsV3(IOpenApiWriter writer)
+        {
+            Utils.CheckArgumentNull(writer);
+
+            // If references have been inlined we don't need the to render the components section
+            // however if they have cycles, then we will need a component rendered
+            if (writer.GetSettings().InlineLocalReferences)
+            {
+                RenderComponents(writer, (writer, element) => element.SerializeAsV3(writer));
                 return;
             }
 
             writer.WriteStartObject();
+            SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer),
+                (writer, referenceElement) => referenceElement.SerializeAsV3(writer));
+        }
 
+        /// 
+        /// Serialize .
+        /// 
+        private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
+            Action callback, Action action)
+        {
             // Serialize each referenceable object as full object without reference if the reference in the object points to itself.
             // If the reference exists but points to other objects, the object is serialized to just that reference.
 
@@ -126,14 +172,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 Schemas,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.Schema} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiSchemaReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -143,14 +188,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 Responses,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.Response} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiResponseReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -160,14 +204,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 Parameters,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.Parameter} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiParameterReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -177,14 +220,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 Examples,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.Example} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiExampleReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -194,14 +236,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 RequestBodies,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.RequestBody} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiRequestBodyReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -211,14 +252,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 Headers,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.Header} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiHeaderReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -228,14 +268,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 SecuritySchemes,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.SecurityScheme} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiSecuritySchemeReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -245,14 +284,13 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 Links,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.Link} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiLinkReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
@@ -262,20 +300,29 @@ public void SerializeAsV3(IOpenApiWriter writer)
                 Callbacks,
                 (w, key, component) =>
                 {
-                    if (component.Reference is {Type: ReferenceType.Callback} &&
-                        component.Reference.Id == key)
+                    if (component is OpenApiCallbackReference reference)
                     {
-                        component.SerializeAsV3WithoutReference(w);
+                        action(w, reference);
                     }
                     else
                     {
-                        component.SerializeAsV3(w);
+                        callback(w, component);
                     }
                 });
 
             // extensions
-            writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0);
+            writer.WriteExtensions(Extensions, version);
+            writer.WriteEndObject();
+        }
 
+        private void RenderComponents(IOpenApiWriter writer, Action callback)
+        {
+            var loops = writer.GetSettings().LoopDetector.Loops;
+            writer.WriteStartObject();
+            if (loops.TryGetValue(typeof(OpenApiSchema), out List
         public const string OpenApi = "openapi";
 
+        /// 
+        /// Field: Json
+        /// 
+        public const string Json = "json";
+
+        /// 
+        /// Field: Yaml
+        /// 
+        public const string Yaml = "yaml";
+
+        /// 
+        /// Field: Yml
+        /// 
+        public const string Yml = "yml";
+
         /// 
         /// Field: Info
         /// 
         public const string Info = "info";
 
+        /// 
+        /// Field: JsonSchemaDialect
+        /// 
+        public const string JsonSchemaDialect = "jsonSchemaDialect";
+
+        /// 
+        /// Field: Webhooks
+        /// 
+        public const string Webhooks = "webhooks";
+
         /// 
         /// Field: Title
         /// 
@@ -35,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
         /// 
@@ -75,6 +160,11 @@ public static class OpenApiConstants
         /// 
         public const string Components = "components";
 
+        /// 
+        /// Field: PathItems
+        /// 
+        public const string PathItems = "pathItems";
+
         /// 
         /// Field: Security
         /// 
@@ -120,6 +210,11 @@ public static class OpenApiConstants
         /// 
         public const string Name = "name";
 
+        /// 
+        /// Field: Identifier
+        /// 
+        public const string Identifier = "identifier";
+
         /// 
         /// Field: Namespace
         /// 
@@ -380,6 +475,11 @@ public static class OpenApiConstants
         /// 
         public const string Properties = "properties";
 
+        /// 
+        /// Field: Pattern Properties
+        /// 
+        public const string PatternProperties = "patternProperties";
+
         /// 
         /// Field: AdditionalProperties
         /// 
@@ -580,6 +680,36 @@ public static class OpenApiConstants
         /// 
         public static readonly Uri defaultUrl = new("http://localhost/");
 
+        /// 
+        /// Field: V3 JsonSchema Reference Uri
+        /// 
+        public const string V3ReferenceUri = "https://registry/components/schemas/";
+
+        /// 
+        /// Field: V2 JsonSchema Reference Uri
+        /// 
+        public const string V2ReferenceUri = "https://registry/definitions/";
+
+        /// 
+        /// The default registry uri for OpenApi documents and workspaces
+        /// 
+        public const string BaseRegistryUri = "https://openapi.net/";
+
+        /// 
+        /// The components path segment in a $ref value.
+        /// 
+        public const string ComponentsSegment = "/components/";
+
+        /// 
+        /// Field: Null
+        /// 
+        public const string Null = "null";
+
+        /// 
+        /// Field: Nullable extension
+        /// 
+        public const string NullableExtension = "x-nullable";
+
         #region V2.0
 
         /// 
diff --git a/src/Microsoft.OpenApi/Models/OpenApiContact.cs b/src/Microsoft.OpenApi/Models/OpenApiContact.cs
index 365b96807..15d67cc76 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiContact.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiContact.cs
@@ -50,6 +50,15 @@ public OpenApiContact(OpenApiContact contact)
             Extensions = contact?.Extensions != null ? new Dictionary(contact.Extensions) : null;
         }
 
+        /// 
+        /// Serialize  to Open Api v3.1
+        /// 
+        /// 
+        public void SerializeAsV31(IOpenApiWriter writer)
+        {
+            WriteInternal(writer, OpenApiSpecVersion.OpenApi3_1);
+        }
+
         /// 
         /// Serialize  to Open Api v3.0
         /// 
@@ -68,6 +77,8 @@ public void SerializeAsV2(IOpenApiWriter writer)
 
         private void WriteInternal(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
         {
+            Utils.CheckArgumentNull(writer);
+
             writer.WriteStartObject();
 
             // name
diff --git a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs
index bb98be623..342025f9f 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs
@@ -10,7 +10,7 @@ namespace Microsoft.OpenApi.Models
     /// 
     /// Discriminator object.
     /// 
-    public class OpenApiDiscriminator : IOpenApiSerializable
+    public class OpenApiDiscriminator : IOpenApiSerializable, IOpenApiExtensible
     {
         /// 
         /// REQUIRED. The name of the property in the payload that will hold the discriminator value.
@@ -22,6 +22,11 @@ public class OpenApiDiscriminator : IOpenApiSerializable
         /// 
         public IDictionary Mapping { get; set; } = new Dictionary();
 
+        /// 
+        /// This object MAY be extended with Specification Extensions.
+        /// 
+        public IDictionary Extensions { get; set; } = new Dictionary();
+
         /// 
         /// Parameter-less constructor
         /// 
@@ -34,12 +39,38 @@ public OpenApiDiscriminator(OpenApiDiscriminator discriminator)
         {
             PropertyName = discriminator?.PropertyName ?? PropertyName;
             Mapping = discriminator?.Mapping != null ? new Dictionary(discriminator.Mapping) : null;
+            Extensions = discriminator?.Extensions != null ? new Dictionary(discriminator.Extensions) : null;
+        }
+
+        /// 
+        /// Serialize  to Open Api v3.1
+        /// 
+        /// 
+        public void SerializeAsV31(IOpenApiWriter writer)
+        {
+            SerializeInternal(writer);
+
+            // extensions
+            writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_1);
+
+            writer.WriteEndObject();
         }
 
         /// 
         /// Serialize  to Open Api v3.0
         /// 
         public void SerializeAsV3(IOpenApiWriter writer)
+        {
+            SerializeInternal(writer);
+
+            writer.WriteEndObject();
+        }
+
+        /// 
+        /// Serialize  to Open Api v3.0
+        /// 
+        /// 
+        private void SerializeInternal(IOpenApiWriter writer)
         {
             Utils.CheckArgumentNull(writer);
 
@@ -50,8 +81,6 @@ public void SerializeAsV3(IOpenApiWriter writer)
 
             // mapping
             writer.WriteOptionalMap(OpenApiConstants.Mapping, Mapping, (w, s) => w.WriteValue(s));
-
-            writer.WriteEndObject();
         }
 
         /// 
diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs
index 1a7035793..0baf31e68 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs
@@ -7,12 +7,17 @@
 using System.Linq;
 using System.Security.Cryptography;
 using System.Text;
-using Microsoft.OpenApi.Exceptions;
+using System.Threading;
+using System.Threading.Tasks;
 using Microsoft.OpenApi.Extensions;
 using Microsoft.OpenApi.Interfaces;
+using Microsoft.OpenApi.Models.References;
+using Microsoft.OpenApi.Reader;
 using Microsoft.OpenApi.Services;
 using Microsoft.OpenApi.Writers;
 
+#nullable enable
+
 namespace Microsoft.OpenApi.Models
 {
     /// 
@@ -21,49 +26,62 @@ namespace Microsoft.OpenApi.Models
     public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenApiAnnotatable
     {
         /// 
-        /// Related workspace containing OpenApiDocuments that are referenced in this document
+        /// Related workspace containing components that are referenced in a document
         /// 
-        public OpenApiWorkspace Workspace { get; set; }
+        public OpenApiWorkspace? Workspace { get; set; }
 
         /// 
         /// REQUIRED. Provides metadata about the API. The metadata MAY be used by tooling as required.
         /// 
         public OpenApiInfo Info { get; set; }
 
+        /// 
+        /// The default value for the $schema keyword within Schema Objects contained within this OAS document. This MUST be in the form of a URI.
+        /// 
+        public string? JsonSchemaDialect { get; set; }
+
         /// 
         /// An array of Server Objects, which provide connectivity information to a target server.
         /// 
-        public IList Servers { get; set; } = new List();
+        public IList? Servers { get; set; } = new List();
 
         /// 
         /// REQUIRED. The available paths and operations for the API.
         /// 
         public OpenApiPaths Paths { get; set; }
 
+        /// 
+        /// The incoming webhooks that MAY be received as part of this API and that the API consumer MAY choose to implement.
+        /// A map of requests initiated other than by an API call, for example by an out of band registration. 
+        /// The key name is a unique string to refer to each webhook, while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider and the expected responses
+        /// 
+        public IDictionary? Webhooks { get; set; } = new Dictionary();
+
         /// 
         /// An element to hold various schemas for the specification.
         /// 
-        public OpenApiComponents Components { get; set; }
+        public OpenApiComponents? Components { get; set; }
 
         /// 
         /// A declaration of which security mechanisms can be used across the API.
         /// 
-        public IList SecurityRequirements { get; set; } = new List();
+        public IList? SecurityRequirements { get; set; } =
+            new List();
 
         /// 
         /// A list of tags used by the specification with additional metadata.
         /// 
-        public IList Tags { get; set; } = new List();
+        public IList? Tags { get; set; } = new List();
 
         /// 
         /// Additional external documentation.
         /// 
-        public OpenApiExternalDocs ExternalDocs { get; set; }
+        public OpenApiExternalDocs? ExternalDocs { get; set; }
 
         /// 
         /// This object MAY be extended with Specification Extensions.
         /// 
-        public IDictionary Extensions { get; set; } = new Dictionary();
+        public IDictionary? Extensions { get; set; } = new Dictionary();
 
         /// 
         /// The unique hash code of the generated OpenAPI document
@@ -71,28 +89,79 @@ public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenAp
         public string HashCode => GenerateHashValue(this);
 
         /// 
-        public IDictionary Annotations { get; set; }
+        public IDictionary? Annotations { get; set; }
 
         /// 
-        /// Parameter-less constructor
+        /// Implements IBaseDocument
         /// 
-        public OpenApiDocument() {}
+        public Uri BaseUri { get; }
 
+        /// 
+        /// Parameter-less constructor
+        /// 
+        public OpenApiDocument() 
+        {
+            Workspace = new OpenApiWorkspace();
+            BaseUri = new(OpenApiConstants.BaseRegistryUri + Guid.NewGuid());
+            Info = new OpenApiInfo();
+            Paths = new OpenApiPaths();
+        }
+                
         /// 
         /// Initializes a copy of an an  object
         /// 
-        public OpenApiDocument(OpenApiDocument document)
+        public OpenApiDocument(OpenApiDocument? document)
         {
             Workspace = document?.Workspace != null ? new(document?.Workspace) : null;
-            Info = document?.Info != null ? new(document?.Info) : null;
+            Info = document?.Info != null ? new(document?.Info) : new OpenApiInfo();
+            JsonSchemaDialect = document?.JsonSchemaDialect ?? JsonSchemaDialect;
             Servers = document?.Servers != null ? new List(document.Servers) : null;
-            Paths = document?.Paths != null ? new(document?.Paths) : null;
+            Paths = document?.Paths != null ? new(document?.Paths) : new OpenApiPaths();
+            Webhooks = document?.Webhooks != null ? new Dictionary(document.Webhooks) : null;
             Components = document?.Components != null ? new(document?.Components) : null;
             SecurityRequirements = document?.SecurityRequirements != null ? new List(document.SecurityRequirements) : null;
             Tags = document?.Tags != null ? new List(document.Tags) : null;
             ExternalDocs = document?.ExternalDocs != null ? new(document?.ExternalDocs) : null;
             Extensions = document?.Extensions != null ? new Dictionary(document.Extensions) : null;
             Annotations = document?.Annotations != null ? new Dictionary(document.Annotations) : null;
+            BaseUri = document?.BaseUri != null ? document.BaseUri : new(OpenApiConstants.BaseRegistryUri + Guid.NewGuid());
+        }
+
+        /// 
+        /// Serialize  to Open API v3.1 document.
+        /// 
+        /// 
+        public void SerializeAsV31(IOpenApiWriter writer)
+        {
+            Utils.CheckArgumentNull(writer);
+
+            writer.WriteStartObject();
+
+            // openApi;
+            writer.WriteProperty(OpenApiConstants.OpenApi, "3.1.0");
+
+            // jsonSchemaDialect
+            writer.WriteProperty(OpenApiConstants.JsonSchemaDialect, JsonSchemaDialect);
+
+            SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (w, element) => element.SerializeAsV31(w));
+
+            // webhooks
+            writer.WriteOptionalMap(
+            OpenApiConstants.Webhooks,
+            Webhooks,
+            (w, key, component) =>
+            {
+                if (component is OpenApiPathItemReference reference)
+                {
+                    reference.SerializeAsV31(w);
+                }
+                else
+                {
+                    component.SerializeAsV31(w);
+                }
+            });
+
+            writer.WriteEndObject();
         }
 
         /// 
@@ -106,35 +175,45 @@ public void SerializeAsV3(IOpenApiWriter writer)
 
             // openapi
             writer.WriteProperty(OpenApiConstants.OpenApi, "3.0.1");
+            SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (w, element) => element.SerializeAsV3(w));
+            writer.WriteEndObject();
+        }
 
+        /// 
+        /// Serialize 
+        /// 
+        /// 
+        /// 
+        /// 
+        private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
+            Action callback)
+        {
             // info
-            writer.WriteRequiredObject(OpenApiConstants.Info, Info, (w, i) => i.SerializeAsV3(w));
+            writer.WriteRequiredObject(OpenApiConstants.Info, Info, callback);
 
             // servers
-            writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, (w, s) => s.SerializeAsV3(w));
+            writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, callback);
 
-            // paths
-            writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, (w, p) => p.SerializeAsV3(w));
+            // paths            
+            writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, callback);
 
             // components
-            writer.WriteOptionalObject(OpenApiConstants.Components, Components, (w, c) => c.SerializeAsV3(w));
+            writer.WriteOptionalObject(OpenApiConstants.Components, Components, callback);
 
             // security
             writer.WriteOptionalCollection(
                 OpenApiConstants.Security,
                 SecurityRequirements,
-                (w, s) => s.SerializeAsV3(w));
+                callback);
 
             // tags
-            writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => t.SerializeAsV3WithoutReference(w));
+            writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => callback(w, t));
 
             // external docs
-            writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV3(w));
+            writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, callback);
 
             // extensions
-            writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0);
-
-            writer.WriteEndObject();
+            writer.WriteExtensions(Extensions, version);
         }
 
         /// 
@@ -164,10 +243,10 @@ public void SerializeAsV2(IOpenApiWriter writer)
             {
                 var loops = writer.GetSettings().LoopDetector.Loops;
 
-                if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas))
+                if (loops.TryGetValue(typeof(OpenApiSchema), out List