From 92dc278b5671bf972e7c9687e2d908c0424ba0ac Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 15 Apr 2024 18:16:38 +0300 Subject: [PATCH 01/29] Use JsonSchema.NET's Evaluate() method to validate a Json schema instance --- .../Validations/Rules/RuleHelpers.cs | 255 +----------------- 1 file changed, 13 insertions(+), 242 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index 076869ad6..d1a338218 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -1,12 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using System.Linq; -using System.Text.Json; using System.Text.Json.Nodes; using Json.Schema; -using Microsoft.OpenApi.Extensions; namespace Microsoft.OpenApi.Validations.Rules { @@ -48,255 +46,28 @@ public static void ValidateDataTypeMismatch( JsonNode value, JsonSchema schema) { - if (schema == null) - { - return; - } + schema ??= null; - // Resolve the Json schema in memory before validating the data types. - var reference = schema.GetRef(); - if (reference != null) + var results = schema.Evaluate(value, new EvaluationOptions() { - var referencePath = string.Concat("https://registry", reference.OriginalString.Split('#').Last()); - var resolvedSchema = (JsonSchema)SchemaRegistry.Global.Get(new Uri(referencePath)); - schema = resolvedSchema ?? schema; - } - - var type = schema.GetJsonType()?.GetDisplayName(); - var format = schema.GetFormat()?.Key; - var jsonElement = JsonSerializer.Deserialize(value); - - // Before checking the type, check first if the schema allows null. - // If so and the data given is also null, this is allowed for any type. - if (jsonElement.ValueKind is JsonValueKind.Null) - { - return; - } + OutputFormat = OutputFormat.List + }); - if ("object".Equals(type, StringComparison.OrdinalIgnoreCase)) + if (!results.IsValid) { - // It is not against the spec to have a string representing an object value. - // To represent examples of media types that cannot naturally be represented in JSON or YAML, - // a string value can contain the example with escaping where necessary - if (jsonElement.ValueKind is JsonValueKind.String) - { - return; - } - - // If value is not a string and also not an object, there is a data mismatch. - if (jsonElement.ValueKind is not JsonValueKind.Object) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - return; - } - - if (value is JsonObject anyObject) + foreach (var detail in results.Details) { - foreach (var property in anyObject) + if (detail.Errors != null && detail.Errors.Any()) { - context.Enter(property.Key); - if ((schema.GetProperties()?.TryGetValue(property.Key, out var propertyValue)) ?? false) + foreach (var error in detail.Errors) { - ValidateDataTypeMismatch(context, ruleName, anyObject[property.Key], propertyValue); + if (!string.IsNullOrEmpty(error.Key) || !string.IsNullOrEmpty(error.Value.Trim())) + { + context.CreateWarning(ruleName, string.Format("{0} : {1} at {2}", error.Key, error.Value.Trim(), detail.InstanceLocation)); + } } - else - { - ValidateDataTypeMismatch(context, ruleName, anyObject[property.Key], schema.GetAdditionalProperties()); - } - - context.Exit(); } } - - return; - } - - if ("array".Equals(type, StringComparison.OrdinalIgnoreCase)) - { - // It is not against the spec to have a string representing an array value. - // To represent examples of media types that cannot naturally be represented in JSON or YAML, - // a string value can contain the example with escaping where necessary - if (jsonElement.ValueKind is JsonValueKind.String) - { - return; - } - - // If value is not a string and also not an array, there is a data mismatch. - if (value is not JsonArray) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - return; - } - - var anyArray = value as JsonArray; - - for (int i = 0; i < anyArray.Count; i++) - { - context.Enter(i.ToString()); - - ValidateDataTypeMismatch(context, ruleName, anyArray[i], schema.GetItems()); - - context.Exit(); - } - - return; - } - - if ("integer".Equals(type, StringComparison.OrdinalIgnoreCase) && - "int32".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.Number) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("integer".Equals(type, StringComparison.OrdinalIgnoreCase) && - "int64".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.Number) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("integer".Equals(type, StringComparison.OrdinalIgnoreCase) && - jsonElement.ValueKind is not JsonValueKind.Number) - { - if (jsonElement.ValueKind is not JsonValueKind.Number) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("number".Equals(type, StringComparison.OrdinalIgnoreCase) && - "float".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.Number) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("number".Equals(type, StringComparison.OrdinalIgnoreCase) && - "double".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.Number) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("number".Equals(type, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.Number) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("string".Equals(type, StringComparison.OrdinalIgnoreCase) && - "byte".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.String) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("string".Equals(type, StringComparison.OrdinalIgnoreCase) && - "date".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.String) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("string".Equals(type, StringComparison.OrdinalIgnoreCase) && - "date-time".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.String) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("string".Equals(type, StringComparison.OrdinalIgnoreCase) && - "password".Equals(format, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.String) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("string".Equals(type, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.String) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; - } - - if ("boolean".Equals(type, StringComparison.OrdinalIgnoreCase)) - { - if (jsonElement.ValueKind is not JsonValueKind.True and not JsonValueKind.False) - { - context.CreateWarning( - ruleName, - DataTypeMismatchedErrorMessage); - } - - return; } } } From b90aa0322fa33f8af97ca7109ae9bc4a2d337264 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 15 Apr 2024 18:16:59 +0300 Subject: [PATCH 02/29] Remove unnecessary using --- src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs index c362f7334..0443b9fb8 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs @@ -5,7 +5,6 @@ using System.Linq; using Json.Schema; using Json.Schema.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Properties; From 681f60a81cb69acdd2811e85aca4f0e9394fb51a Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 15 Apr 2024 18:32:02 +0300 Subject: [PATCH 03/29] Add a null check --- .../Validations/Rules/RuleHelpers.cs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index d1a338218..ca28d5be7 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -46,29 +46,30 @@ public static void ValidateDataTypeMismatch( JsonNode value, JsonSchema schema) { - schema ??= null; - - var results = schema.Evaluate(value, new EvaluationOptions() + if ( schema is not null) { - OutputFormat = OutputFormat.List - }); + var results = schema.Evaluate(value, new EvaluationOptions() + { + OutputFormat = OutputFormat.List + }); - if (!results.IsValid) - { - foreach (var detail in results.Details) + if (!results.IsValid) { - if (detail.Errors != null && detail.Errors.Any()) + foreach (var detail in results.Details) { - foreach (var error in detail.Errors) + if (detail.Errors != null && detail.Errors.Any()) { - if (!string.IsNullOrEmpty(error.Key) || !string.IsNullOrEmpty(error.Value.Trim())) + foreach (var error in detail.Errors) { - context.CreateWarning(ruleName, string.Format("{0} : {1} at {2}", error.Key, error.Value.Trim(), detail.InstanceLocation)); + if (!string.IsNullOrEmpty(error.Key) || !string.IsNullOrEmpty(error.Value.Trim())) + { + context.CreateWarning(ruleName, string.Format("{0} : {1} at {2}", error.Key, error.Value.Trim(), detail.InstanceLocation)); + } } } } } - } + } } } } From e8d504f849620610edfa5dc8aa08db490f7f7807 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 16 Apr 2024 13:10:51 +0300 Subject: [PATCH 04/29] Make method public to expose it to clients --- src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs index 78efb6221..807f271f2 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.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; @@ -204,7 +204,13 @@ public static Type MapJsonSchemaValueTypeToSimpleType(this JsonSchema schema) return result; } - internal static string ConvertSchemaValueTypeToString(SchemaValueType value) + /// + /// Converts the Schema value type to its string equivalent + /// + /// + /// + /// + public static string ConvertSchemaValueTypeToString(SchemaValueType value) { return value switch { From 1ecc6fda7fe9689814d7a21b784b453f11ea6586 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 16 Apr 2024 13:11:07 +0300 Subject: [PATCH 05/29] Remove whitespace --- src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index ca28d5be7..d617747b0 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -45,8 +45,8 @@ public static void ValidateDataTypeMismatch( string ruleName, JsonNode value, JsonSchema schema) - { - if ( schema is not null) + { + if (schema is not null) { var results = schema.Evaluate(value, new EvaluationOptions() { From 1d6b0a686ad7a71774297cbda3c234044cdfe582 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 16 Apr 2024 16:58:36 +0300 Subject: [PATCH 06/29] Decorate the nullable keyword with SchemaSpecVersion attribute for evaluation --- src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs b/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs index 11118a207..c37e23d8f 100644 --- a/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs @@ -206,6 +206,7 @@ public void Evaluate(EvaluationContext context) /// The nullable keyword /// [SchemaKeyword(Name)] + [SchemaSpecVersion(SpecVersion.Draft202012)] public class NullableKeyword : IJsonSchemaKeyword { /// From f770dd64ad393467642c296a1117bf1508c2e2d7 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 17 Apr 2024 17:51:35 +0300 Subject: [PATCH 07/29] Update assertions with correct test output post validation --- .../OpenApiHeaderValidationTests.cs | 16 ++++---- .../OpenApiMediaTypeValidationTests.cs | 19 +++++----- .../OpenApiParameterValidationTests.cs | 23 ++++++----- .../OpenApiSchemaValidationTests.cs | 38 +++++++++---------- 4 files changed, 50 insertions(+), 46 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs index df1e0b620..945180e1e 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.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.Collections.Generic; @@ -108,16 +108,16 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, + "type : Value is \"string\" but should be \"object\" at ", + "type : Value is \"string\" but should be \"integer\" at /y", + "type : Value is \"string\" but should be \"integer\" at /z", + "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { - // #enum/0 is not an error since the spec allows - // representing an object using a string. - "#/examples/example1/value/y", - "#/examples/example1/value/z", + "#/examples/example0/value", + "#/examples/example1/value", + "#/examples/example1/value", "#/examples/example2/value" }); } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs index f36339a20..3886de28e 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.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.Collections.Generic; @@ -9,7 +9,6 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Services; -using Microsoft.OpenApi.Validations.Rules; using Xunit; namespace Microsoft.OpenApi.Validations.Tests @@ -40,7 +39,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage + "type : Value is \"integer\" but should be \"string\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { @@ -105,17 +104,19 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, + "type : Value is \"string\" but should be \"object\" at ", + "type : Value is \"string\" but should be \"integer\" at /y", + "type : Value is \"string\" but should be \"integer\" at /z", + "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { // #enum/0 is not an error since the spec allows // representing an object using a string. - "#/examples/example1/value/y", - "#/examples/example1/value/z", - "#/examples/example2/value" + "#/examples/example0/value", + "#/examples/example1/value", + "#/examples/example1/value", + "#/examples/example2/value" }); } } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs index 480c41393..c21f1bc16 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.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; @@ -14,6 +14,7 @@ using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; using Xunit; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace Microsoft.OpenApi.Validations.Tests { @@ -23,8 +24,8 @@ public class OpenApiParameterValidationTests public void ValidateFieldIsRequiredInParameter() { // Arrange - var nameError = String.Format(SRResource.Validation_FieldIsRequired, "name", "parameter"); - var inError = String.Format(SRResource.Validation_FieldIsRequired, "in", "parameter"); + var nameError = string.Format(SRResource.Validation_FieldIsRequired, "name", "parameter"); + var inError = string.Format(SRResource.Validation_FieldIsRequired, "in", "parameter"); var parameter = new OpenApiParameter(); // Act @@ -90,7 +91,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage + "type : Value is \"integer\" but should be \"string\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { @@ -159,17 +160,19 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, + "type : Value is \"string\" but should be \"object\" at ", + "type : Value is \"string\" but should be \"integer\" at /y", + "type : Value is \"string\" but should be \"integer\" at /z", + "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { // #enum/0 is not an error since the spec allows // representing an object using a string. - "#/{parameter1}/examples/example1/value/y", - "#/{parameter1}/examples/example1/value/z", - "#/{parameter1}/examples/example2/value" + "#/{parameter1}/examples/example0/value", + "#/{parameter1}/examples/example1/value", + "#/{parameter1}/examples/example1/value", + "#/{parameter1}/examples/example2/value" }); } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs index 14a6082e5..e4da87e3a 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.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; @@ -40,7 +40,7 @@ public void ValidateDefaultShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage + "type : Value is \"integer\" but should be \"string\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { @@ -72,7 +72,7 @@ public void ValidateExampleAndDefaultShouldNotHaveDataTypeMismatchForSimpleSchem result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage + "type : Value is \"integer\" but should be \"string\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { @@ -116,16 +116,16 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, + "type : Value is \"string\" but should be \"object\" at ", + "type : Value is \"string\" but should be \"integer\" at /y", + "type : Value is \"string\" but should be \"integer\" at /z", + "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { - // #enum/0 is not an error since the spec allows - // representing an object using a string. - "#/enum/1/y", - "#/enum/1/z", + "#/enum/0", + "#/enum/1", + "#/enum/1", "#/enum/2" }); } @@ -160,7 +160,7 @@ public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() new JsonSchemaBuilder() .Type(SchemaValueType.String) .Build())) - .Default(new OpenApiAny(new JsonObject() + .Default(new JsonObject() { ["property1"] = new JsonArray() { @@ -179,8 +179,8 @@ public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() } }, ["property3"] = "123", - ["property4"] = DateTime.UtcNow - }).Node).Build(); + ["property4"] = DateTime.UtcNow.ToString() + }).Build(); // Act var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); @@ -194,15 +194,15 @@ public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() result.Should().BeTrue(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, - RuleHelpers.DataTypeMismatchedErrorMessage, + "type : Value is \"string\" but should be \"integer\" at /property1/2", + "type : Value is \"integer\" but should be \"object\" at /property2/0", + "type : Value is \"string\" but should be \"boolean\" at /property2/1/z", }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { - "#/default/property1/2", - "#/default/property2/0", - "#/default/property2/1/z" + "#/default", + "#/default", + "#/default" }); } From 6ac327fa7e55e22b79928ab5377c1f6e586e6cbd Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 22 Apr 2024 11:14:48 +0300 Subject: [PATCH 08/29] Fix failing test --- .../Validations/OpenApiHeaderValidationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs index 945180e1e..62c56b430 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs @@ -41,7 +41,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - RuleHelpers.DataTypeMismatchedErrorMessage + "type : Value is \"integer\" but should be \"string\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { From 3f058f497561a596ae95edd53526504bf4c286f1 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 22 Apr 2024 15:39:51 +0300 Subject: [PATCH 09/29] Refactor code to create JSON schema mappings without a Ref in the components --- .../Reader/ParseNodes/MapNode.cs | 20 +------------------ .../Reader/ParseNodes/ParseNode.cs | 2 +- .../Reader/V2/OpenApiDocumentDeserializer.cs | 2 +- .../V3/OpenApiComponentsDeserializer.cs | 9 ++------- 4 files changed, 5 insertions(+), 28 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs index 620f648a3..def4f17a2 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs @@ -79,7 +79,7 @@ public override Dictionary CreateMap(Func k.key, v => v.value); } - public override Dictionary CreateJsonSchemaMapWithReference( + public override Dictionary CreateJsonSchemaMap( ReferenceType referenceType, Func map, OpenApiSpecVersion version) @@ -101,24 +101,6 @@ public override Dictionary CreateJsonSchemaMapWithReference( { 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.GetRef() == null) - { - var builder = new JsonSchemaBuilder(); - - // construct the Ref and append it to the builder - var reference = version == OpenApiSpecVersion.OpenApi2_0 ? string.Concat("#/definitions/", entry.key) : - string.Concat("#/components/schemas/", entry.key); - - builder.Ref(reference); - - // Append all the keywords in original schema to our new schema using a builder instance - foreach (var keyword in entry.value.Keywords) - { - builder.Add(keyword); - } - entry.value = builder.Build(); - } } finally { diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs index a28989227..1fff7c3a3 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs @@ -59,7 +59,7 @@ public virtual Dictionary CreateMap(Func CreateJsonSchemaMapWithReference( + public virtual Dictionary CreateJsonSchemaMap( ReferenceType referenceType, Func map, OpenApiSpecVersion version) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs index 0f814616f..0d7fba829 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs @@ -60,7 +60,7 @@ internal static partial class OpenApiV2Deserializer (o, n) => { o.Components ??= new(); - o.Components.Schemas = n.CreateJsonSchemaMapWithReference(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi2_0); + o.Components.Schemas = n.CreateJsonSchemaMap(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi2_0); } }, { diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs index a6ca78101..8471d7b68 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs @@ -1,11 +1,6 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Nodes; -using Json.Schema; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -20,7 +15,7 @@ internal static partial class OpenApiV3Deserializer { private static readonly FixedFieldMap _componentsFixedFields = new() { - {"schemas", (o, n) => o.Schemas = n.CreateJsonSchemaMapWithReference(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi3_0)}, + {"schemas", (o, n) => o.Schemas = n.CreateJsonSchemaMap(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi3_0)}, {"responses", (o, n) => o.Responses = n.CreateMap(LoadResponse)}, {"parameters", (o, n) => o.Parameters = n.CreateMap(LoadParameter)}, {"examples", (o, n) => o.Examples = n.CreateMap(LoadExample)}, From 6e7c5a8b38cac4071fd30c0f35c27849ffe912b0 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 22 Apr 2024 16:03:24 +0300 Subject: [PATCH 10/29] Fix failing tests --- .../V2Tests/OpenApiDocumentTests.cs | 2 -- .../V3Tests/JsonSchemaTests.cs | 2 -- .../V3Tests/OpenApiDocumentTests.cs | 6 ------ 3 files changed, 10 deletions(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index 4449072e0..df26255db 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -140,10 +140,8 @@ public void ShouldParseProducesInAnyOrder() Schemas = { ["Item"] = new JsonSchemaBuilder() - .Ref("#/definitions/Item") .Properties(("id", new JsonSchemaBuilder().Type(SchemaValueType.String).Description("Item identifier."))), ["Error"] = new JsonSchemaBuilder() - .Ref("#/definitions/Error") .Properties( ("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Format("int32")), ("message", new JsonSchemaBuilder().Type(SchemaValueType.String)), diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs index b69c5add0..dd98bdb92 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs @@ -229,14 +229,12 @@ public void ParseBasicSchemaWithReferenceShouldSucceed() Schemas = { ["ErrorModel"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/ErrorModel") .Type(SchemaValueType.Object) .Required("message", "code") .Properties( ("message", new JsonSchemaBuilder().Type(SchemaValueType.String)), ("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Minimum(100).Maximum(600))), ["ExtendedErrorModel"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/ExtendedErrorModel") .AllOf( new JsonSchemaBuilder() .Ref("#/components/schemas/ErrorModel"), diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index e68e25991..ecd680642 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -215,7 +215,6 @@ public void ParseStandardPetStoreDocumentShouldSucceed() Schemas = new Dictionary { ["pet1"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/pet1") .Type(SchemaValueType.Object) .Required("id", "name") .Properties( @@ -223,7 +222,6 @@ public void ParseStandardPetStoreDocumentShouldSucceed() ("name", new JsonSchemaBuilder().Type(SchemaValueType.String)), ("tag", new JsonSchemaBuilder().Type(SchemaValueType.String))), ["newPet"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/newPet") .Type(SchemaValueType.Object) .Required("name") .Properties( @@ -231,7 +229,6 @@ public void ParseStandardPetStoreDocumentShouldSucceed() ("name", new JsonSchemaBuilder().Type(SchemaValueType.String)), ("tag", new JsonSchemaBuilder().Type(SchemaValueType.String))), ["errorModel"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/errorModel") .Type(SchemaValueType.Object) .Required("code", "message") .Properties( @@ -529,7 +526,6 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() Schemas = new Dictionary { ["pet1"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/pet1") .Type(SchemaValueType.Object) .Required("id", "name") .Properties( @@ -537,7 +533,6 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() ("name", new JsonSchemaBuilder().Type(SchemaValueType.String)), ("tag", new JsonSchemaBuilder().Type(SchemaValueType.String))), ["newPet"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/newPet") .Type(SchemaValueType.Object) .Required("name") .Properties( @@ -545,7 +540,6 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() ("name", new JsonSchemaBuilder().Type(SchemaValueType.String)), ("tag", new JsonSchemaBuilder().Type(SchemaValueType.String))), ["errorModel"] = new JsonSchemaBuilder() - .Ref("#/components/schemas/errorModel") .Type(SchemaValueType.Object) .Required("code", "message") .Properties( From e76101a582b59d94a98f6103fe05c3d908ef79ef Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 23 Apr 2024 17:53:33 +0300 Subject: [PATCH 11/29] Adds an optional host document param to use during validation in order to get the local Json schema registry --- .../Extensions/OpenApiElementExtensions.cs | 6 ++++ .../Services/OpenApiWorkspace.cs | 7 +++- .../Validations/IValidationContext.cs | 7 ++++ .../Validations/OpenApiValidator.cs | 9 ++++- .../Validations/Rules/RuleHelpers.cs | 35 +++++++++++++------ 5 files changed, 52 insertions(+), 12 deletions(-) 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/Services/OpenApiWorkspace.cs b/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs index ca3fb32d0..f8ca95a13 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs @@ -65,7 +65,7 @@ public int ComponentsCount() public bool RegisterComponent(string location, T component) { var uri = ToLocationUrl(location); - if (component is IBaseDocument schema) + if (component is JsonSchema schema) { if (!_jsonSchemaRegistry.ContainsKey(uri)) { @@ -162,5 +162,10 @@ private Uri ToLocationUrl(string location) { return new(BaseUrl, location); } + + internal Dictionary GetSchemaRegistry() + { + return _jsonSchemaRegistry; + } } } diff --git a/src/Microsoft.OpenApi/Validations/IValidationContext.cs b/src/Microsoft.OpenApi/Validations/IValidationContext.cs index 73b1fec06..36c26baa6 100644 --- a/src/Microsoft.OpenApi/Validations/IValidationContext.cs +++ b/src/Microsoft.OpenApi/Validations/IValidationContext.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using Microsoft.OpenApi.Models; + namespace Microsoft.OpenApi.Validations { /// @@ -35,5 +37,10 @@ public interface IValidationContext /// Pointer to source of validation error in document /// string PathString { get; } + + /// + /// + /// + OpenApiDocument HostDocument { get; } } } diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index 9f9ce91cd..73c473d61 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -24,9 +24,11 @@ public class OpenApiValidator : OpenApiVisitorBase, IValidationContext /// Create a visitor that will validate an OpenAPIDocument /// /// - public OpenApiValidator(ValidationRuleSet ruleSet) + /// + public OpenApiValidator(ValidationRuleSet ruleSet, OpenApiDocument hostDocument = null) { _ruleSet = ruleSet; + HostDocument = hostDocument; } /// @@ -39,6 +41,11 @@ public OpenApiValidator(ValidationRuleSet ruleSet) /// public IEnumerable Warnings { get => _warnings; } + /// + /// The host document used for validation. + /// + public OpenApiDocument HostDocument { get; set; } + /// /// Register an error with the validation context. /// diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index d617747b0..8ca21126e 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text.Json.Nodes; using Json.Schema; +using Microsoft.OpenApi.Services; namespace Microsoft.OpenApi.Validations.Rules { @@ -48,22 +49,36 @@ public static void ValidateDataTypeMismatch( { if (schema is not null) { - var results = schema.Evaluate(value, new EvaluationOptions() + if (context.HostDocument != null) { - OutputFormat = OutputFormat.List - }); + schema.BaseUri = context.HostDocument.BaseUri; + var options = new EvaluationOptions(); - if (!results.IsValid) - { - foreach (var detail in results.Details) + var registry = context.HostDocument.Workspace.GetSchemaRegistry(); + + foreach(var keyValuePair in registry) + { + var jsonShema = keyValuePair.Value; + var schemaKey = keyValuePair.Key; + options.SchemaRegistry.Register(schemaKey, jsonShema); + } + + options.SchemaRegistry.Register(schema.BaseUri, schema); + + var results = schema.Evaluate(value, options); + + if (!results.IsValid) { - if (detail.Errors != null && detail.Errors.Any()) + foreach (var detail in results.Details) { - foreach (var error in detail.Errors) + if (detail.Errors != null && detail.Errors.Any()) { - if (!string.IsNullOrEmpty(error.Key) || !string.IsNullOrEmpty(error.Value.Trim())) + foreach (var error in detail.Errors) { - context.CreateWarning(ruleName, string.Format("{0} : {1} at {2}", error.Key, error.Value.Trim(), detail.InstanceLocation)); + if (!string.IsNullOrEmpty(error.Key) || !string.IsNullOrEmpty(error.Value.Trim())) + { + context.CreateWarning(ruleName, string.Format("{0} : {1} at {2}", error.Key, error.Value.Trim(), detail.InstanceLocation)); + } } } } From c8292765c6d5f2e3efa65e06b13924cac97f36ed Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 26 Apr 2024 13:17:33 +0300 Subject: [PATCH 12/29] Walk each schema to resolve any present $refs --- .../Validations/Rules/RuleHelpers.cs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index 8ca21126e..fb0b0d79c 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -51,19 +51,12 @@ public static void ValidateDataTypeMismatch( { if (context.HostDocument != null) { - schema.BaseUri = context.HostDocument.BaseUri; - var options = new EvaluationOptions(); - - var registry = context.HostDocument.Workspace.GetSchemaRegistry(); - - foreach(var keyValuePair in registry) - { - var jsonShema = keyValuePair.Value; - var schemaKey = keyValuePair.Key; - options.SchemaRegistry.Register(schemaKey, jsonShema); - } + var visitor = new JsonSchemaReferenceResolver(context.HostDocument); + var walker = new OpenApiWalker(visitor); + schema = walker.Walk(schema); - options.SchemaRegistry.Register(schema.BaseUri, schema); + var options = new EvaluationOptions(); + options.OutputFormat = OutputFormat.List; var results = schema.Evaluate(value, options); From 2baf2f4fc98fb84ed2249c57dfeecfc105c4e486 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 26 Apr 2024 16:00:14 +0300 Subject: [PATCH 13/29] Code cleanup --- .../Extensions/OpenApiTypeMapper.cs | 2 +- .../Validations/Rules/RuleHelpers.cs | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs index bc58cec28..814e716de 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs @@ -136,7 +136,7 @@ public static Type MapJsonSchemaValueTypeToSimpleType(this JsonSchema schema) /// /// /// - public static string ConvertSchemaValueTypeToString(SchemaValueType value) + internal static string ConvertSchemaValueTypeToString(SchemaValueType value) { return value switch { diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index fb0b0d79c..ba8a8926c 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -53,25 +53,25 @@ public static void ValidateDataTypeMismatch( { var visitor = new JsonSchemaReferenceResolver(context.HostDocument); var walker = new OpenApiWalker(visitor); - schema = walker.Walk(schema); + schema = walker.Walk(schema); + } - var options = new EvaluationOptions(); - options.OutputFormat = OutputFormat.List; + var options = new EvaluationOptions(); + options.OutputFormat = OutputFormat.List; - var results = schema.Evaluate(value, options); + var results = schema.Evaluate(value, options); - if (!results.IsValid) + if (!results.IsValid) + { + foreach (var detail in results.Details) { - foreach (var detail in results.Details) + if (detail.Errors != null && detail.Errors.Any()) { - if (detail.Errors != null && detail.Errors.Any()) + foreach (var error in detail.Errors) { - foreach (var error in detail.Errors) + if (!string.IsNullOrEmpty(error.Key) || !string.IsNullOrEmpty(error.Value.Trim())) { - if (!string.IsNullOrEmpty(error.Key) || !string.IsNullOrEmpty(error.Value.Trim())) - { - context.CreateWarning(ruleName, string.Format("{0} : {1} at {2}", error.Key, error.Value.Trim(), detail.InstanceLocation)); - } + context.CreateWarning(ruleName, string.Format("{0} : {1} at {2}", error.Key, error.Value.Trim(), detail.InstanceLocation)); } } } From 4591988891dea3b3102e66543df69abce39d6728 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 26 Apr 2024 16:00:29 +0300 Subject: [PATCH 14/29] Update API interface --- .../Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 15068d24b..a67fac8b4 100755 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -219,6 +219,7 @@ namespace Microsoft.OpenApi.Extensions public static string GetSummary(this Json.Schema.JsonSchema schema) { } } [Json.Schema.SchemaKeyword("nullable")] + [Json.Schema.SchemaSpecVersion(Json.Schema.SpecVersion.Draft202012)] public class NullableKeyword : Json.Schema.IJsonSchemaKeyword { public const string Name = "nullable"; @@ -1514,6 +1515,7 @@ namespace Microsoft.OpenApi.Validations { public interface IValidationContext { + Microsoft.OpenApi.Models.OpenApiDocument HostDocument { get; } string PathString { get; } void AddError(Microsoft.OpenApi.Validations.OpenApiValidatorError error); void AddWarning(Microsoft.OpenApi.Validations.OpenApiValidatorWarning warning); @@ -1522,8 +1524,9 @@ namespace Microsoft.OpenApi.Validations } public class OpenApiValidator : Microsoft.OpenApi.Services.OpenApiVisitorBase, Microsoft.OpenApi.Validations.IValidationContext { - public OpenApiValidator(Microsoft.OpenApi.Validations.ValidationRuleSet ruleSet) { } + public OpenApiValidator(Microsoft.OpenApi.Validations.ValidationRuleSet ruleSet, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null) { } public System.Collections.Generic.IEnumerable Errors { get; } + public Microsoft.OpenApi.Models.OpenApiDocument HostDocument { get; set; } public System.Collections.Generic.IEnumerable Warnings { get; } public void AddError(Microsoft.OpenApi.Validations.OpenApiValidatorError error) { } public void AddWarning(Microsoft.OpenApi.Validations.OpenApiValidatorWarning warning) { } From 3cae500302596d22d9535cc443bbf1b095639a96 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 14:30:12 +0300 Subject: [PATCH 15/29] Adds an optional host document parameter --- .../Reader/ParseNodes/FixedFieldMap.cs | 3 +- .../Reader/ParseNodes/ListNode.cs | 4 +- .../Reader/ParseNodes/MapNode.cs | 9 +- .../Reader/ParseNodes/ParseNode.cs | 7 +- .../Reader/ParseNodes/PatternFieldMap.cs | 3 +- .../Reader/ParseNodes/PropertyNode.cs | 11 +- .../Reader/V2/JsonSchemaDeserializer.cs | 77 ++--- .../Reader/V2/OpenApiContactDeserializer.cs | 8 +- .../Reader/V2/OpenApiDocumentDeserializer.cs | 40 +-- .../V2/OpenApiExternalDocsDeserializer.cs | 6 +- .../Reader/V2/OpenApiHeaderDeserializer.cs | 40 +-- .../Reader/V2/OpenApiInfoDeserializer.cs | 14 +- .../Reader/V2/OpenApiLicenseDeserializer.cs | 8 +- .../Reader/V2/OpenApiOperationDeserializer.cs | 34 +- .../Reader/V2/OpenApiParameterDeserializer.cs | 48 +-- .../Reader/V2/OpenApiPathItemDeserializer.cs | 22 +- .../Reader/V2/OpenApiPathsDeserializer.cs | 6 +- .../Reader/V2/OpenApiResponseDeserializer.cs | 20 +- .../V2/OpenApiSecuritySchemeDeserializer.cs | 18 +- .../Reader/V2/OpenApiTagDeserializer.cs | 8 +- .../Reader/V2/OpenApiV2Deserializer.cs | 5 +- .../Reader/V2/OpenApiXmlDeserializer.cs | 12 +- .../Reader/V3/JsonSchemaDeserializer.cs | 107 ++++--- .../Reader/V3/OpenApiCallbackDeserializer.cs | 8 +- .../V3/OpenApiComponentsDeserializer.cs | 25 +- .../Reader/V3/OpenApiContactDeserializer.cs | 10 +- .../V3/OpenApiDiscriminatorDeserializer.cs | 4 +- .../Reader/V3/OpenApiDocumentDeserializer.cs | 20 +- .../Reader/V3/OpenApiEncodingDeserializer.cs | 12 +- .../Reader/V3/OpenApiExampleDeserializer.cs | 12 +- .../V3/OpenApiExternalDocsDeserializer.cs | 8 +- .../Reader/V3/OpenApiHeaderDeserializer.cs | 24 +- .../Reader/V3/OpenApiInfoDeserializer.cs | 16 +- .../Reader/V3/OpenApiLicenseDeserializer.cs | 8 +- .../Reader/V3/OpenApiLinkDeserializer.cs | 18 +- .../Reader/V3/OpenApiMediaTypeDeserializer.cs | 12 +- .../Reader/V3/OpenApiOAuthFlowDeserializer.cs | 10 +- .../V3/OpenApiOAuthFlowsDeserializer.cs | 10 +- .../Reader/V3/OpenApiOperationDeserializer.cs | 30 +- .../Reader/V3/OpenApiParameterDeserializer.cs | 32 +- .../Reader/V3/OpenApiPathItemDeserializer.cs | 32 +- .../Reader/V3/OpenApiPathsDeserializer.cs | 6 +- .../V3/OpenApiRequestBodyDeserializer.cs | 10 +- .../Reader/V3/OpenApiResponseDeserializer.cs | 14 +- .../Reader/V3/OpenApiResponsesDeserializer.cs | 6 +- .../V3/OpenApiSecuritySchemeDeserializer.cs | 20 +- .../Reader/V3/OpenApiServerDeserializer.cs | 10 +- .../V3/OpenApiServerVariableDeserializer.cs | 10 +- .../Reader/V3/OpenApiTagDeserializer.cs | 8 +- .../Reader/V3/OpenApiV3Deserializer.cs | 5 +- .../Reader/V3/OpenApiXmlDeserializer.cs | 12 +- .../Reader/V31/JsonSchemaDeserializer.cs | 296 +----------------- .../Reader/V31/OpenApiCallbackDeserializer.cs | 8 +- .../V31/OpenApiComponentsDeserializer.cs | 24 +- .../Reader/V31/OpenApiContactDeserializer.cs | 10 +- .../V31/OpenApiDiscriminatorDeserializer.cs | 8 +- .../Reader/V31/OpenApiDocumentDeserializer.cs | 24 +- .../Reader/V31/OpenApiEncodingDeserializer.cs | 14 +- .../Reader/V31/OpenApiExampleDeserializer.cs | 12 +- .../V31/OpenApiExternalDocsDeserializer.cs | 8 +- .../Reader/V31/OpenApiHeaderDeserializer.cs | 28 +- .../Reader/V31/OpenApiInfoDeserializer.cs | 22 +- .../Reader/V31/OpenApiLicenseDeserializer.cs | 10 +- .../Reader/V31/OpenApiLinkDeserializer.cs | 18 +- .../V31/OpenApiMediaTypeDeserializer.cs | 18 +- .../V31/OpenApiOAuthFlowDeserializer.cs | 10 +- .../V31/OpenApiOAuthFlowsDeserializer.cs | 10 +- .../V31/OpenApiOperationDeserializer.cs | 44 +-- .../V31/OpenApiParameterDeserializer.cs | 38 +-- .../Reader/V31/OpenApiPathItemDeserializer.cs | 32 +- .../Reader/V31/OpenApiPathsDeserializer.cs | 6 +- .../V31/OpenApiRequestBodyDeserializer.cs | 12 +- .../Reader/V31/OpenApiResponseDeserializer.cs | 20 +- .../V31/OpenApiResponsesDeserializer.cs | 6 +- .../V31/OpenApiSecuritySchemeDeserializer.cs | 22 +- .../Reader/V31/OpenApiServerDeserializer.cs | 12 +- .../V31/OpenApiServerVariableDeserializer.cs | 10 +- .../Reader/V31/OpenApiTagDeserializer.cs | 10 +- .../Reader/V31/OpenApiV31Deserializer.cs | 5 +- .../Reader/V31/OpenApiXmlDeserializer.cs | 12 +- .../V3Tests/OpenApiDocumentTests.cs | 1 + 81 files changed, 693 insertions(+), 959 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/FixedFieldMap.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/FixedFieldMap.cs index f972a2c29..139f38c6a 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/FixedFieldMap.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/FixedFieldMap.cs @@ -3,10 +3,11 @@ using System; using System.Collections.Generic; +using Microsoft.OpenApi.Models; namespace Microsoft.OpenApi.Reader.ParseNodes { - internal class FixedFieldMap : Dictionary> + internal class FixedFieldMap : Dictionary> { } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/ListNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/ListNode.cs index e5646a359..306a2f559 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/ListNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/ListNode.cs @@ -22,14 +22,14 @@ public ListNode(ParsingContext context, JsonArray jsonArray) : base( _nodeList = jsonArray; } - public override List CreateList(Func map) + public override List CreateList(Func map, OpenApiDocument hostDocument = null) { if (_nodeList == null) { throw new OpenApiReaderException($"Expected list while parsing {typeof(T).Name}", _nodeList); } - return _nodeList?.Select(n => map(new MapNode(Context, n as JsonObject), null)) + return _nodeList?.Select(n => map(new MapNode(Context, n as JsonObject), hostDocument)) .Where(i => i != null) .ToList(); } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs index def4f17a2..0cc8539cf 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs @@ -49,7 +49,7 @@ public PropertyNode this[string key] } } - public override Dictionary CreateMap(Func map) + public override Dictionary CreateMap(Func map, OpenApiDocument hostDocument = null) { var jsonMap = _node ?? throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context); var nodes = jsonMap.Select( @@ -62,7 +62,7 @@ public override Dictionary CreateMap(Func CreateMap(Func CreateJsonSchemaMap( ReferenceType referenceType, Func map, - OpenApiSpecVersion version) + OpenApiSpecVersion version, + OpenApiDocument hostDocument = null) { var jsonMap = _node ?? throw new OpenApiReaderException($"Expected map while parsing {typeof(JsonSchema).Name}", Context); @@ -95,7 +96,7 @@ public override Dictionary CreateJsonSchemaMap( { Context.StartObject(key); entry = (key, - value: map(new MapNode(Context, (JsonObject)n.Value), null) + value: map(new MapNode(Context, (JsonObject)n.Value), hostDocument) ); if (entry.value == null) { diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs index 1fff7c3a3..a72f1bed9 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/ParseNode.cs @@ -49,12 +49,12 @@ public static ParseNode Create(ParsingContext context, JsonNode node) return new ValueNode(context, node as JsonValue); } - public virtual List CreateList(Func map) + public virtual List CreateList(Func map, OpenApiDocument hostDocument = null) { throw new OpenApiReaderException("Cannot create list from this type of node.", Context); } - public virtual Dictionary CreateMap(Func map) + public virtual Dictionary CreateMap(Func map, OpenApiDocument hostDocument = null) { throw new OpenApiReaderException("Cannot create map from this type of node.", Context); } @@ -62,7 +62,8 @@ public virtual Dictionary CreateMap(Func CreateJsonSchemaMap( ReferenceType referenceType, Func map, - OpenApiSpecVersion version) + OpenApiSpecVersion version, + OpenApiDocument hostDocument = null) { throw new OpenApiReaderException("Cannot create map from this reference.", Context); } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/PatternFieldMap.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/PatternFieldMap.cs index fce08dac5..79caf3221 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/PatternFieldMap.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/PatternFieldMap.cs @@ -3,10 +3,11 @@ using System; using System.Collections.Generic; +using Microsoft.OpenApi.Models; namespace Microsoft.OpenApi.Reader.ParseNodes { - internal class PatternFieldMap : Dictionary, Action> + internal class PatternFieldMap : Dictionary, Action> { } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/PropertyNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/PropertyNode.cs index a9a6d3b46..9b59771d5 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/PropertyNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/PropertyNode.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; @@ -26,15 +26,16 @@ public PropertyNode(ParsingContext context, string name, JsonNode node) : base( public void ParseField( T parentInstance, - IDictionary> fixedFields, - IDictionary, Action> patternFields) + IDictionary> fixedFields, + IDictionary, Action> patternFields, + OpenApiDocument hostDocument = null) { if (fixedFields.TryGetValue(Name, out var fixedFieldMap)) { try { Context.StartObject(Name); - fixedFieldMap(parentInstance, Value); + fixedFieldMap(parentInstance, Value, hostDocument); } catch (OpenApiReaderException ex) { @@ -58,7 +59,7 @@ public void ParseField( try { Context.StartObject(Name); - map(parentInstance, Name, Value); + map(parentInstance, Name, Value, hostDocument); } catch (OpenApiReaderException ex) { diff --git a/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs index 17309527c..f9ff3fc26 100644 --- a/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs @@ -22,103 +22,103 @@ internal static partial class OpenApiV2Deserializer private static readonly FixedFieldMap _schemaFixedFields = new() { { - "title", (o, n) => + "title", (o, n, _) => { o.Title(n.GetScalarValue()); } }, { - "multipleOf", (o, n) => + "multipleOf", (o, n, _) => { o.MultipleOf(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { - "maximum", (o, n) => + "maximum", (o, n, _) => { o.Maximum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { - "exclusiveMaximum", (o, n) => + "exclusiveMaximum", (o, n, _) => { o.ExclusiveMaximum(bool.Parse(n.GetScalarValue())); } }, { - "minimum", (o, n) => + "minimum", (o, n, _) => { o.Minimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { - "exclusiveMinimum", (o, n) => + "exclusiveMinimum", (o, n, _) => { o.ExclusiveMinimum(bool.Parse(n.GetScalarValue())); } }, { - "maxLength", (o, n) => + "maxLength", (o, n, _) => { o.MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minLength", (o, n) => + "minLength", (o, n, _) => { o.MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "pattern", (o, n) => + "pattern", (o, n, _) => { o.Pattern(n.GetScalarValue()); } }, { - "maxItems", (o, n) => + "maxItems", (o, n, _) => { o.MaxItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minItems", (o, n) => + "minItems", (o, n, _) => { o.MinItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "uniqueItems", (o, n) => + "uniqueItems", (o, n, _) => { o.UniqueItems(bool.Parse(n.GetScalarValue())); } }, { - "maxProperties", (o, n) => + "maxProperties", (o, n, _) => { o.MaxProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minProperties", (o, n) => + "minProperties", (o, n, _) => { o.MinProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "required", (o, n) => + "required", (o, n, _) => { o.Required(new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))); } }, { - "enum", (o, n) => + "enum", (o, n, _) => { o.Enum(n.CreateListOfAny()); } }, { - "type", (o, n) => + "type", (o, n, _) => { if(n is ListNode) { @@ -131,25 +131,25 @@ internal static partial class OpenApiV2Deserializer } }, { - "allOf", (o, n) => + "allOf", (o, n, t) => { - o.AllOf(n.CreateList(LoadSchema)); + o.AllOf(n.CreateList(LoadSchema, t)); } }, { - "items", (o, n) => + "items", (o, n, t) => { - o.Items(LoadSchema(n)); + o.Items(LoadSchema(n, t)); } }, { - "properties", (o, n) => + "properties", (o, n, t) => { - o.Properties(n.CreateMap(LoadSchema)); + o.Properties(n.CreateMap(LoadSchema, t)); } }, { - "additionalProperties", (o, n) => + "additionalProperties", (o, n, t) => { if (n is ValueNode) { @@ -157,30 +157,30 @@ internal static partial class OpenApiV2Deserializer } else { - o.AdditionalProperties(LoadSchema(n)); + o.AdditionalProperties(LoadSchema(n, t)); } } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description(n.GetScalarValue()); } }, { - "format", (o, n) => + "format", (o, n, _) => { o.Format(n.GetScalarValue()); } }, { - "default", (o, n) => + "default", (o, n, _) => { o.Default(n.CreateAny().Node); } }, { - "discriminator", (o, n) => + "discriminator", (o, n, _) => { var discriminator = new OpenApiDiscriminator { @@ -191,29 +191,29 @@ internal static partial class OpenApiV2Deserializer } }, { - "readOnly", (o, n) => + "readOnly", (o, n, _) => { o.ReadOnly(bool.Parse(n.GetScalarValue())); } }, { - "xml", (o, n) => + "xml", (o, n, t) => { - var xml = LoadXml(n); + var xml = LoadXml(n, t); o.Xml(xml.Namespace, xml.Name, xml.Prefix, xml.Attribute, xml.Wrapped, (IReadOnlyDictionary)xml.Extensions); } }, { - "externalDocs", (o, n) => + "externalDocs", (o, n, t) => { - var externalDocs = LoadExternalDocs(n); + var externalDocs = LoadExternalDocs(n, t); o.ExternalDocs(externalDocs.Url, externalDocs.Description, (IReadOnlyDictionary)externalDocs.Extensions); } }, { - "example", (o, n) => + "example", (o, n, _) => { o.Example(n.CreateAny().Node); } @@ -222,7 +222,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _schemaPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} }; public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument = null) @@ -243,6 +243,11 @@ public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument } var schema = schemaBuilder.Build(); + + if (hostDocument != null) + { + schema.BaseUri = hostDocument.BaseUri; + } return schema; } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs index 2d92ca97d..2cb8dea9c 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs @@ -18,21 +18,21 @@ internal static partial class OpenApiV2Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, t) => o.Name = n.GetScalarValue() }, { "url", - (o, n) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, t) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { "email", - (o, n) => o.Email = n.GetScalarValue() + (o, n, t) => o.Email = n.GetScalarValue() }, }; private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs index 0d7fba829..3e449ff82 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs @@ -22,21 +22,21 @@ internal static partial class OpenApiV2Deserializer private static readonly FixedFieldMap _openApiFixedFields = new() { { - "swagger", (_, _) => {} + "swagger", (_, _, _) => {} /* Version is valid field but we already parsed it */ }, - {"info", (o, n) => o.Info = LoadInfo(n)}, - {"host", (_, n) => n.Context.SetTempStorage("host", n.GetScalarValue())}, - {"basePath", (_, n) => n.Context.SetTempStorage("basePath", n.GetScalarValue())}, + {"info", (o, n, _) => o.Info = LoadInfo(n, o)}, + {"host", (_, n, _) => n.Context.SetTempStorage("host", n.GetScalarValue())}, + {"basePath", (_, n, _) => n.Context.SetTempStorage("basePath", n.GetScalarValue())}, { - "schemes", (_, n) => n.Context.SetTempStorage( + "schemes", (_, n, _) => n.Context.SetTempStorage( "schemes", n.CreateSimpleList( (s, p) => s.GetScalarValue())) }, { "consumes", - (_, n) => + (_, n, _) => { var consumes = n.CreateSimpleList((s, p) => s.GetScalarValue()); if (consumes.Count > 0) @@ -46,7 +46,7 @@ internal static partial class OpenApiV2Deserializer } }, { - "produces", (_, n) => { + "produces", (_, n, _) => { var produces = n.CreateSimpleList((s, p) => s.GetScalarValue()); if (produces.Count > 0) { @@ -54,25 +54,25 @@ internal static partial class OpenApiV2Deserializer } } }, - {"paths", (o, n) => o.Paths = LoadPaths(n)}, + {"paths", (o, n, _) => o.Paths = LoadPaths(n, o)}, { "definitions", - (o, n) => + (o, n, _) => { o.Components ??= new(); - o.Components.Schemas = n.CreateJsonSchemaMap(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi2_0); + o.Components.Schemas = n.CreateJsonSchemaMap(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi2_0, o); } }, { "parameters", - (o, n) => + (o, n, _) => { if (o.Components == null) { o.Components = new(); } - o.Components.Parameters = n.CreateMap(LoadParameter); + o.Components.Parameters = n.CreateMap(LoadParameter, o); o.Components.RequestBodies = n.CreateMap((p, d) => { @@ -83,36 +83,36 @@ internal static partial class OpenApiV2Deserializer } }, { - "responses", (o, n) => + "responses", (o, n, _) => { if (o.Components == null) { o.Components = new(); } - o.Components.Responses = n.CreateMap(LoadResponse); + o.Components.Responses = n.CreateMap(LoadResponse, o); } }, { - "securityDefinitions", (o, n) => + "securityDefinitions", (o, n, _) => { if (o.Components == null) { o.Components = new(); } - o.Components.SecuritySchemes = n.CreateMap(LoadSecurityScheme); + o.Components.SecuritySchemes = n.CreateMap(LoadSecurityScheme, o); } }, - {"security", (o, n) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement)}, - {"tags", (o, n) => o.Tags = n.CreateList(LoadTag)}, - {"externalDocs", (o, n) => o.ExternalDocs = LoadExternalDocs(n)} + {"security", (o, n, _) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement, o)}, + {"tags", (o, n, _) => o.Tags = n.CreateList(LoadTag, o)}, + {"externalDocs", (o, n, _) => o.ExternalDocs = LoadExternalDocs(n, o)} }; private static readonly 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))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static void MakeServers(IList servers, ParsingContext context, RootNode rootNode) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs index 6a68640a6..8e90fb4e7 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs @@ -19,18 +19,18 @@ internal static partial class OpenApiV2Deserializer { { OpenApiConstants.Description, - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { OpenApiConstants.Url, - (o, n) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, }; private static readonly PatternFieldMap _externalDocsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs index 3f36a262c..4c2431721 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs @@ -22,104 +22,104 @@ internal static partial class OpenApiV2Deserializer { { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { - "type", (o, n) => + "type", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().Type(SchemaTypeConverter.ConvertToSchemaValueType(n.GetScalarValue())); } }, { - "format", (o, n) => + "format", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().Format(n.GetScalarValue()); } }, { - "items", (o, n) => + "items", (o, n, t) => { - o.Schema = GetOrCreateHeaderSchemaBuilder().Items(LoadSchema(n)); + o.Schema = GetOrCreateHeaderSchemaBuilder().Items(LoadSchema(n, t)); } }, { "collectionFormat", - (o, n) => LoadStyle(o, n.GetScalarValue()) + (o, n, _) => LoadStyle(o, n.GetScalarValue()) }, { - "default", (o, n) => + "default", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().Default(n.CreateAny().Node); } }, { - "maximum", (o, n) => + "maximum", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().Maximum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "exclusiveMaximum", (o, n) => + "exclusiveMaximum", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().ExclusiveMaximum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minimum", (o, n) => + "minimum", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().Minimum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "exclusiveMinimum", (o, n) => + "exclusiveMinimum", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().ExclusiveMinimum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "maxLength", (o, n) => + "maxLength", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minLength", (o, n) => + "minLength", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "pattern", (o, n) => + "pattern", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().Pattern(n.GetScalarValue()); } }, { - "maxItems", (o, n) => + "maxItems", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().MaxItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minItems", (o, n) => + "minItems", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().MinItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "uniqueItems", (o, n) => + "uniqueItems", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().UniqueItems(bool.Parse(n.GetScalarValue())); } }, { - "multipleOf", (o, n) => + "multipleOf", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().MultipleOf(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "enum", (o, n) => + "enum", (o, n, _) => { o.Schema = GetOrCreateHeaderSchemaBuilder().Enum(n.CreateListOfAny()).Build(); } @@ -128,7 +128,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static JsonSchemaBuilder GetOrCreateHeaderSchemaBuilder() diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs index 824aab028..90a8535b1 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs @@ -18,33 +18,33 @@ internal static partial class OpenApiV2Deserializer { { "title", - (o, n) => o.Title = n.GetScalarValue() + (o, n, _) => o.Title = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "termsOfService", - (o, n) => o.TermsOfService = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.TermsOfService = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { "contact", - (o, n) => o.Contact = LoadContact(n) + (o, n, t) => o.Contact = LoadContact(n, t) }, { "license", - (o, n) => o.License = LoadLicense(n) + (o, n, t) => o.License = LoadLicense(n, t) }, { "version", - (o, n) => o.Version = n.GetScalarValue() + (o, n, _) => o.Version = n.GetScalarValue() } }; private static readonly PatternFieldMap _infoPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs index 46062dcef..f1f7a7b93 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs @@ -18,17 +18,17 @@ internal static partial class OpenApiV2Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { "url", - (o, n) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, }; private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument = null) @@ -37,7 +37,7 @@ public static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDoc var license = new OpenApiLicense(); - ParseMap(mapNode, license, _licenseFixedFields, _licensePatternFields); + ParseMap(mapNode, license, _licenseFixedFields, _licensePatternFields, doc: hostDocument); return license; } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs index 6e8d3d53c..5dfc3b9a1 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.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.Collections.Generic; @@ -22,7 +22,7 @@ internal static partial class OpenApiV2Deserializer new() { { - "tags", (o, n) => o.Tags = n.CreateSimpleList( + "tags", (o, n, doc) => o.Tags = n.CreateSimpleList( (valueNode, doc) => LoadTagByReference( valueNode.Context, @@ -30,26 +30,26 @@ internal static partial class OpenApiV2Deserializer }, { "summary", - (o, n) => o.Summary = n.GetScalarValue() + (o, n, _) => o.Summary = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "externalDocs", - (o, n) => o.ExternalDocs = LoadExternalDocs(n) + (o, n, t) => o.ExternalDocs = LoadExternalDocs(n, t) }, { "operationId", - (o, n) => o.OperationId = n.GetScalarValue() + (o, n, _) => o.OperationId = n.GetScalarValue() }, { "parameters", - (o, n) => o.Parameters = n.CreateList(LoadParameter) + (o, n, t) => o.Parameters = n.CreateList(LoadParameter, t) }, { - "consumes", (_, n) => { + "consumes", (_, n, _) => { var consumes = n.CreateSimpleList((s, p) => s.GetScalarValue()); if (consumes.Count > 0) { n.Context.SetTempStorage(TempStorageKeys.OperationConsumes,consumes); @@ -57,7 +57,7 @@ internal static partial class OpenApiV2Deserializer } }, { - "produces", (_, n) => { + "produces", (_, n, _) => { var produces = n.CreateSimpleList((s, p) => s.GetScalarValue()); if (produces.Count > 0) { n.Context.SetTempStorage(TempStorageKeys.OperationProduces, produces); @@ -66,22 +66,22 @@ internal static partial class OpenApiV2Deserializer }, { "responses", - (o, n) => o.Responses = LoadResponses(n) + (o, n, t) => o.Responses = LoadResponses(n, t) }, { "deprecated", - (o, n) => o.Deprecated = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Deprecated = bool.Parse(n.GetScalarValue()) }, { "security", - (o, n) => o.Security = n.CreateList(LoadSecurityRequirement) + (o, n, t) => o.Security = n.CreateList(LoadSecurityRequirement, t) }, }; private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static readonly FixedFieldMap _responsesFixedFields = new(); @@ -89,8 +89,8 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _responsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n) => o.Add(p, LoadResponse(n))}, - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument = null) @@ -105,7 +105,7 @@ internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument h var operation = new OpenApiOperation(); - ParseMap(mapNode, operation, _operationFixedFields, _operationPatternFields); + ParseMap(mapNode, operation, _operationFixedFields, _operationPatternFields, doc: hostDocument); // Build request body based on information determined while parsing OpenApiOperation var bodyParameter = node.Context.GetFromTempStorage(TempStorageKeys.BodyParameter); @@ -139,7 +139,7 @@ public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hos var domainObject = new OpenApiResponses(); - ParseMap(mapNode, domainObject, _responsesFixedFields, _responsesPatternFields); + ParseMap(mapNode, domainObject, _responsesFixedFields, _responsesPatternFields, doc:hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs index ca1110761..50b0321c7 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.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; @@ -26,7 +26,7 @@ internal static partial class OpenApiV2Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, t) => o.Name = n.GetScalarValue() }, { "in", @@ -34,93 +34,93 @@ internal static partial class OpenApiV2Deserializer }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, t) => o.Description = n.GetScalarValue() }, { "required", - (o, n) => o.Required = bool.Parse(n.GetScalarValue()) + (o, n, t) => o.Required = bool.Parse(n.GetScalarValue()) }, { "deprecated", - (o, n) => o.Deprecated = bool.Parse(n.GetScalarValue()) + (o, n, t) => o.Deprecated = bool.Parse(n.GetScalarValue()) }, { "allowEmptyValue", - (o, n) => o.AllowEmptyValue = bool.Parse(n.GetScalarValue()) + (o, n, t) => o.AllowEmptyValue = bool.Parse(n.GetScalarValue()) }, { - "type", (o, n) => + "type", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().Type(SchemaTypeConverter.ConvertToSchemaValueType(n.GetScalarValue())); } }, { - "items", (o, n) => + "items", (o, n, t) => { - o.Schema = GetOrCreateParameterSchemaBuilder().Items(LoadSchema(n)); + o.Schema = GetOrCreateParameterSchemaBuilder().Items(LoadSchema(n, t)); } }, { "collectionFormat", - (o, n) => LoadStyle(o, n.GetScalarValue()) + (o, n, t) => LoadStyle(o, n.GetScalarValue()) }, { - "format", (o, n) => + "format", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().Format(n.GetScalarValue()); } }, { - "minimum", (o, n) => + "minimum", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().Minimum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "maximum", (o, n) => + "maximum", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().Maximum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "maxLength", (o, n) => + "maxLength", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minLength", (o, n) => + "minLength", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "readOnly", (o, n) => + "readOnly", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().ReadOnly(bool.Parse(n.GetScalarValue())); } }, { - "default", (o, n) => + "default", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().Default(n.CreateAny().Node); } }, { - "pattern", (o, n) => + "pattern", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().Pattern(n.GetScalarValue()); } }, { - "enum", (o, n) => + "enum", (o, n, t) => { o.Schema = GetOrCreateParameterSchemaBuilder().Enum(n.CreateListOfAny()).Build(); } }, { "schema", - (o, n) => o.Schema = LoadSchema(n) + (o, n, t) => o.Schema = LoadSchema(n, t) }, { "x-examples", @@ -132,7 +132,7 @@ internal static partial class OpenApiV2Deserializer new() { {s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), - (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static void LoadStyle(OpenApiParameter p, string v) @@ -164,7 +164,7 @@ private static void LoadStyle(OpenApiParameter p, string v) } } - private static void LoadParameterExamplesExtension(OpenApiParameter parameter, ParseNode node) + private static void LoadParameterExamplesExtension(OpenApiParameter parameter, ParseNode node, OpenApiDocument hostDocument = null) { var examples = LoadExamplesExtension(node); node.Context.SetTempStorage(TempStorageKeys.Examples, examples, parameter); @@ -176,7 +176,7 @@ private static JsonSchemaBuilder GetOrCreateParameterSchemaBuilder() return _parameterJsonSchemaBuilder; } - private static void ProcessIn(OpenApiParameter o, ParseNode n) + private static void ProcessIn(OpenApiParameter o, ParseNode n, OpenApiDocument hostDocument = null) { var value = n.GetScalarValue(); switch (value) @@ -230,7 +230,7 @@ public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBod var parameter = new OpenApiParameter(); _parameterJsonSchemaBuilder = null; - ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields); + ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields, doc: hostDocument); var schema = node.Context.GetFromTempStorage("schema"); if (schema != null) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs index 574ce8619..71fd2e736 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs @@ -18,19 +18,19 @@ internal static partial class OpenApiV2Deserializer private static readonly FixedFieldMap _pathItemFixedFields = new() { { - "$ref", (o, n) => + "$ref", (o, n, t) => { o.Reference = new() { ExternalResource = n.GetScalarValue() }; o.UnresolvedReference =true; } }, - {"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))}, + {"get", (o, n, t) => o.AddOperation(OperationType.Get, LoadOperation(n, t))}, + {"put", (o, n, t) => o.AddOperation(OperationType.Put, LoadOperation(n, t))}, + {"post", (o, n, t) => o.AddOperation(OperationType.Post, LoadOperation(n, t))}, + {"delete", (o, n, t) => o.AddOperation(OperationType.Delete, LoadOperation(n, t))}, + {"options", (o, n, t) => o.AddOperation(OperationType.Options, LoadOperation(n, t))}, + {"head", (o, n, t) => o.AddOperation(OperationType.Head, LoadOperation(n, t))}, + {"patch", (o, n, t) => o.AddOperation(OperationType.Patch, LoadOperation(n, t))}, { "parameters", LoadPathParameters @@ -40,7 +40,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}, }; public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument = null) @@ -49,12 +49,12 @@ public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostD var pathItem = new OpenApiPathItem(); - ParseMap(mapNode, pathItem, _pathItemFixedFields, _pathItemPatternFields); + ParseMap(mapNode, pathItem, _pathItemFixedFields, _pathItemPatternFields, doc: hostDocument); return pathItem; } - private static void LoadPathParameters(OpenApiPathItem pathItem, ParseNode node) + private static void LoadPathParameters(OpenApiPathItem pathItem, ParseNode node, OpenApiDocument hostDocument = null) { node.Context.SetTempStorage(TempStorageKeys.BodyParameter, null); node.Context.SetTempStorage(TempStorageKeys.FormParameters, null); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs index 6d23aef0b..9e0c0f08b 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs @@ -17,8 +17,8 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n) => o.Add(k, LoadPathItem(n))}, - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument = null) @@ -27,7 +27,7 @@ public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocumen var domainObject = new OpenApiPaths(); - ParseMap(mapNode, domainObject, _pathsFixedFields, _pathsPatternFields); + ParseMap(mapNode, domainObject, _pathsFixedFields, _pathsPatternFields, doc: hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs index 2b612c488..05b89cfff 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.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; @@ -21,23 +21,21 @@ internal static partial class OpenApiV2Deserializer { { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "headers", - (o, n) => o.Headers = n.CreateMap(LoadHeader) + (o, n, t) => o.Headers = n.CreateMap(LoadHeader, t) }, { - "examples", - LoadExamples + "examples", LoadExamples }, { - "x-examples", - LoadResponseExamplesExtension + "x-examples", LoadResponseExamplesExtension }, { "schema", - (o, n) => n.Context.SetTempStorage(TempStorageKeys.ResponseSchema, LoadSchema(n), o) + (o, n, t) => n.Context.SetTempStorage(TempStorageKeys.ResponseSchema, LoadSchema(n, t), o) }, }; @@ -45,7 +43,7 @@ internal static partial class OpenApiV2Deserializer new() { {s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), - (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static readonly AnyFieldMap _mediaTypeAnyFields = @@ -107,7 +105,7 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P context.SetTempStorage(TempStorageKeys.ResponseProducesSet, true, response); } - private static void LoadResponseExamplesExtension(OpenApiResponse response, ParseNode node) + private static void LoadResponseExamplesExtension(OpenApiResponse response, ParseNode node, OpenApiDocument hostDocument = null) { var examples = LoadExamplesExtension(node); node.Context.SetTempStorage(TempStorageKeys.Examples, examples, response); @@ -148,7 +146,7 @@ private static Dictionary LoadExamplesExtension(ParseNod return examples; } - private static void LoadExamples(OpenApiResponse response, ParseNode node) + private static void LoadExamples(OpenApiResponse response, ParseNode node, OpenApiDocument hostDocument = null) { var mapNode = node.CheckMapNode("examples"); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs index 9223ecc3f..4e142b479 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs @@ -23,7 +23,7 @@ internal static partial class OpenApiV2Deserializer { { "type", - (o, n) => + (o, n, _) => { var type = n.GetScalarValue(); switch (type) @@ -43,29 +43,29 @@ internal static partial class OpenApiV2Deserializer } } }, - {"description", (o, n) => o.Description = n.GetScalarValue()}, - {"name", (o, n) => o.Name = n.GetScalarValue()}, - {"in", (o, n) => o.In = n.GetScalarValue().GetEnumFromDisplayName()}, + {"description", (o, n, _) => o.Description = n.GetScalarValue()}, + {"name", (o, n, _) => o.Name = n.GetScalarValue()}, + {"in", (o, n, _) => o.In = n.GetScalarValue().GetEnumFromDisplayName()}, { - "flow", (_, n) => _flowValue = n.GetScalarValue() + "flow", (_, n, _) => _flowValue = n.GetScalarValue() }, { "authorizationUrl", - (_, n) => _flow.AuthorizationUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (_, n, _) => _flow.AuthorizationUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { "tokenUrl", - (_, n) => _flow.TokenUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (_, n, _) => _flow.TokenUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { - "scopes", (_, n) => _flow.Scopes = n.CreateSimpleMap(LoadString) + "scopes", (_, n, _) => _flow.Scopes = n.CreateSimpleMap(LoadString) } }; private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs index 2eccdb929..47c3c6a40 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs @@ -17,21 +17,21 @@ internal static partial class OpenApiV2Deserializer { { OpenApiConstants.Name, - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { OpenApiConstants.Description, - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { OpenApiConstants.ExternalDocs, - (o, n) => o.ExternalDocs = LoadExternalDocs(n) + (o, n, t) => o.ExternalDocs = LoadExternalDocs(n, t) } }; private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs index 34dac28ea..06c6b4c1f 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs @@ -23,7 +23,8 @@ private static void ParseMap( T domainObject, FixedFieldMap fixedFieldMap, PatternFieldMap patternFieldMap, - List requiredFields = null) + List requiredFields = null, + OpenApiDocument doc = null) { if (mapNode == null) { @@ -33,7 +34,7 @@ private static void ParseMap( var allFields = fixedFieldMap.Keys.Union(mapNode.Select(static x => x.Name)); foreach (var propertyNode in allFields) { - mapNode[propertyNode]?.ParseField(domainObject, fixedFieldMap, patternFieldMap); + mapNode[propertyNode]?.ParseField(domainObject, fixedFieldMap, patternFieldMap, doc); requiredFields?.Remove(propertyNode); } } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs index 9e0728e87..c630bd941 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs @@ -19,10 +19,10 @@ internal static partial class OpenApiV2Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { - "namespace", (o, n) => + "namespace", (o, n, _) => { if (Uri.IsWellFormedUriString(n.GetScalarValue(), UriKind.Absolute)) { @@ -36,22 +36,22 @@ internal static partial class OpenApiV2Deserializer }, { "prefix", - (o, n) => o.Prefix = n.GetScalarValue() + (o, n, _) => o.Prefix = n.GetScalarValue() }, { "attribute", - (o, n) => o.Attribute = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Attribute = bool.Parse(n.GetScalarValue()) }, { "wrapped", - (o, n) => o.Wrapped = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Wrapped = bool.Parse(n.GetScalarValue()) }, }; private static readonly PatternFieldMap _xmlPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/JsonSchemaDeserializer.cs index 90c1f5984..0f6be069a 100644 --- a/src/Microsoft.OpenApi/Reader/V3/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/JsonSchemaDeserializer.cs @@ -23,103 +23,103 @@ internal static partial class OpenApiV3Deserializer private static readonly FixedFieldMap _schemaFixedFields = new() { { - "title", (o, n) => + "title", (o, n, _) => { o.Title(n.GetScalarValue()); } }, { - "multipleOf", (o, n) => + "multipleOf", (o, n, _) => { o.MultipleOf(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { - "maximum", (o, n) => + "maximum", (o, n, _) => { o.Maximum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { - "exclusiveMaximum", (o, n) => + "exclusiveMaximum", (o, n, _) => { o.ExclusiveMaximum(bool.Parse(n.GetScalarValue())); } }, { - "minimum", (o, n) => + "minimum", (o, n, _) => { o.Minimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { - "exclusiveMinimum", (o, n) => + "exclusiveMinimum", (o, n, _) => { o.ExclusiveMinimum(bool.Parse(n.GetScalarValue())); } }, { - "maxLength", (o, n) => + "maxLength", (o, n, _) => { o.MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minLength", (o, n) => + "minLength", (o, n, _) => { o.MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "pattern", (o, n) => + "pattern", (o, n, _) => { o.Pattern(n.GetScalarValue()); } }, { - "maxItems", (o, n) => + "maxItems", (o, n, _) => { o.MaxItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minItems", (o, n) => + "minItems", (o, n, _) => { o.MinItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "uniqueItems", (o, n) => + "uniqueItems", (o, n, _) => { o.UniqueItems(bool.Parse(n.GetScalarValue())); } }, { - "maxProperties", (o, n) => + "maxProperties", (o, n, _) => { o.MaxProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "minProperties", (o, n) => + "minProperties", (o, n, _) => { o.MinProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { - "required", (o, n) => + "required", (o, n, _) => { o.Required(new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))); } }, { - "enum", (o, n) => + "enum", (o, n, _) => { o.Enum(n.CreateListOfAny()); } }, { - "type", (o, n) => + "type", (o, n, _) => { if(n is ListNode) { @@ -132,43 +132,43 @@ internal static partial class OpenApiV3Deserializer } }, { - "allOf", (o, n) => + "allOf", (o, n, t) => { - o.AllOf(n.CreateList(LoadSchema)); + o.AllOf(n.CreateList(LoadSchema, t)); } }, { - "oneOf", (o, n) => + "oneOf", (o, n, t) => { - o.OneOf(n.CreateList(LoadSchema)); + o.OneOf(n.CreateList(LoadSchema, t)); } }, { - "anyOf", (o, n) => + "anyOf", (o, n, t) => { - o.AnyOf(n.CreateList(LoadSchema)); + o.AnyOf(n.CreateList(LoadSchema, t)); } }, { - "not", (o, n) => + "not", (o, n, t) => { - o.Not(LoadSchema(n)); + o.Not(LoadSchema(n, t)); } }, { - "items", (o, n) => + "items", (o, n, t) => { - o.Items(LoadSchema(n)); + o.Items(LoadSchema(n, t)); } }, { - "properties", (o, n) => + "properties", (o, n, t) => { - o.Properties(n.CreateMap(LoadSchema)); + o.Properties(n.CreateMap(LoadSchema, t)); } }, { - "additionalProperties", (o, n) => + "additionalProperties", (o, n, t) => { if (n is ValueNode) { @@ -176,71 +176,71 @@ internal static partial class OpenApiV3Deserializer } else { - o.AdditionalProperties(LoadSchema(n)); + o.AdditionalProperties(LoadSchema(n, t)); } } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description(n.GetScalarValue()); } }, { - "format", (o, n) => + "format", (o, n, _) => { o.Format(n.GetScalarValue()); } }, { - "default", (o, n) => + "default", (o, n, _) => { o.Default(n.CreateAny().Node); } }, { - "nullable", (o, n) => + "nullable", (o, n, _) => { o.Nullable(bool.Parse(n.GetScalarValue())); } }, { - "discriminator", (o, n) => + "discriminator", (o, n, t) => { - var discriminator = LoadDiscriminator(n); + var discriminator = LoadDiscriminator(n, t); o.Discriminator(discriminator); } }, { - "readOnly", (o, n) => + "readOnly", (o, n, _) => { o.ReadOnly(bool.Parse(n.GetScalarValue())); } }, { - "writeOnly", (o, n) => + "writeOnly", (o, n, _) => { o.WriteOnly(bool.Parse(n.GetScalarValue())); } }, { - "xml", (o, n) => + "xml", (o, n, t) => { - var xml = LoadXml(n); + var xml = LoadXml(n, t); o.Xml(xml.Namespace, xml.Name, xml.Prefix, xml.Attribute, xml.Wrapped, (IReadOnlyDictionary)xml.Extensions); } }, { - "externalDocs", (o, n) => + "externalDocs", (o, n, t) => { - var externalDocs = LoadExternalDocs(n); + var externalDocs = LoadExternalDocs(n, t); o.ExternalDocs(externalDocs.Url, externalDocs.Description, (IReadOnlyDictionary)externalDocs.Extensions); } }, { - "example", (o, n) => + "example", (o, n, _) => { if(n is ListNode) { @@ -253,7 +253,7 @@ internal static partial class OpenApiV3Deserializer } }, { - "deprecated", (o, n) => + "deprecated", (o, n, _) => { o.Deprecated(bool.Parse(n.GetScalarValue())); } @@ -262,7 +262,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _schemaPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} }; public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument = null) @@ -274,15 +274,26 @@ public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument var pointer = mapNode.GetReferencePointer(); if (pointer != null) { - return builder.Ref(pointer); + var jsonSchema = builder.Ref(pointer).Build(); + if (hostDocument != null) + { + jsonSchema.BaseUri = hostDocument.BaseUri; + } + + return jsonSchema; } foreach (var propertyNode in mapNode) { - propertyNode.ParseField(builder, _schemaFixedFields, _schemaPatternFields); + propertyNode.ParseField(builder, _schemaFixedFields, _schemaPatternFields, hostDocument); } var schema = builder.Build(); + + if (hostDocument != null) + { + schema.BaseUri = hostDocument.BaseUri; + } return schema; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs index fe6db9646..faf50ebb1 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.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.Linq; @@ -21,8 +21,8 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _callbackPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n))}, - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}, + {s => !s.StartsWith("x-"), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static OpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument = null) @@ -39,7 +39,7 @@ public static OpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostD var domainObject = new OpenApiCallback(); - ParseMap(mapNode, domainObject, _callbackFixedFields, _callbackPatternFields); + ParseMap(mapNode, domainObject, _callbackFixedFields, _callbackPatternFields, hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs index 8471d7b68..3e1d2539b 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs @@ -1,6 +1,7 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using Json.Schema; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -15,21 +16,21 @@ internal static partial class OpenApiV3Deserializer { private static readonly FixedFieldMap _componentsFixedFields = new() { - {"schemas", (o, n) => o.Schemas = n.CreateJsonSchemaMap(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi3_0)}, - {"responses", (o, n) => o.Responses = n.CreateMap(LoadResponse)}, - {"parameters", (o, n) => o.Parameters = n.CreateMap(LoadParameter)}, - {"examples", (o, n) => o.Examples = n.CreateMap(LoadExample)}, - {"requestBodies", (o, n) => o.RequestBodies = n.CreateMap(LoadRequestBody)}, - {"headers", (o, n) => o.Headers = n.CreateMap(LoadHeader)}, - {"securitySchemes", (o, n) => o.SecuritySchemes = n.CreateMap(LoadSecurityScheme)}, - {"links", (o, n) => o.Links = n.CreateMap(LoadLink)}, - {"callbacks", (o, n) => o.Callbacks = n.CreateMap(LoadCallback)} + {"schemas", (o, n, t) => o.Schemas = n.CreateJsonSchemaMap(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi3_0, t)}, + {"responses", (o, n, t) => o.Responses = n.CreateMap(LoadResponse, t)}, + {"parameters", (o, n, t) => o.Parameters = n.CreateMap(LoadParameter, t)}, + {"examples", (o, n, t) => o.Examples = n.CreateMap(LoadExample, t)}, + {"requestBodies", (o, n, t) => o.RequestBodies = n.CreateMap(LoadRequestBody, t)}, + {"headers", (o, n, t) => o.Headers = n.CreateMap(LoadHeader, t)}, + {"securitySchemes", (o, n, t) => o.SecuritySchemes = n.CreateMap(LoadSecurityScheme, t)}, + {"links", (o, n, t) => o.Links = n.CreateMap(LoadLink, t)}, + {"callbacks", (o, n, t) => o.Callbacks = n.CreateMap(LoadCallback, t)} }; private static readonly PatternFieldMap _componentsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument hostDocument = null) @@ -37,7 +38,7 @@ public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument h var mapNode = node.CheckMapNode("components"); var components = new OpenApiComponents(); - ParseMap(mapNode, components, _componentsFixedFields, _componentsPatternFields); + ParseMap(mapNode, components, _componentsFixedFields, _componentsPatternFields, hostDocument); return components; } } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs index 10a9893f7..e4d98de64 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs @@ -18,21 +18,21 @@ internal static partial class OpenApiV3Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { "email", - (o, n) => o.Email = n.GetScalarValue() + (o, n, _) => o.Email = n.GetScalarValue() }, { "url", - (o, n) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, }; private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument = null) @@ -40,7 +40,7 @@ public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDoc var mapNode = node as MapNode; var contact = new OpenApiContact(); - ParseMap(mapNode, contact, _contactFixedFields, _contactPatternFields); + ParseMap(mapNode, contact, _contactFixedFields, _contactPatternFields, hostDocument); return contact; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiDiscriminatorDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiDiscriminatorDeserializer.cs index e542534bc..c10532c2c 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiDiscriminatorDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiDiscriminatorDeserializer.cs @@ -17,11 +17,11 @@ internal static partial class OpenApiV3Deserializer { { "propertyName", - (o, n) => o.PropertyName = n.GetScalarValue() + (o, n, _) => o.PropertyName = n.GetScalarValue() }, { "mapping", - (o, n) => o.Mapping = n.CreateSimpleMap(LoadString) + (o, n, _) => o.Mapping = n.CreateSimpleMap(LoadString) } }; diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs index 3ed838de9..3fcdb9af7 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs @@ -18,15 +18,15 @@ internal static partial class OpenApiV3Deserializer private static readonly FixedFieldMap _openApiFixedFields = new() { { - "openapi", (_, _) => + "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); + {"info", (o, n, _) => o.Info = LoadInfo(n, o)}, + {"servers", (o, n, _) => o.Servers = n.CreateList(LoadServer, o)}, + {"paths", (o, n, _) => o.Paths = LoadPaths(n, o)}, + {"components", (o, n, _) => o.Components = LoadComponents(n, o)}, + {"tags", (o, n, _) => {o.Tags = n.CreateList(LoadTag, o); foreach (var tag in o.Tags) { tag.Reference = new() @@ -36,14 +36,14 @@ internal static partial class OpenApiV3Deserializer }; } } }, - {"externalDocs", (o, n) => o.ExternalDocs = LoadExternalDocs(n)}, - {"security", (o, n) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement)} + {"externalDocs", (o, n, _) => o.ExternalDocs = LoadExternalDocs(n, o)}, + {"security", (o, n, _) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement, o)} }; private static readonly PatternFieldMap _openApiPatternFields = new PatternFieldMap { // 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))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiDocument LoadOpenApi(RootNode rootNode) @@ -51,7 +51,7 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) var openApiDoc = new OpenApiDocument(); var openApiNode = rootNode.GetMap(); - ParseMap(openApiNode, openApiDoc, _openApiFixedFields, _openApiPatternFields); + ParseMap(openApiNode, openApiDoc, _openApiFixedFields, _openApiPatternFields, openApiDoc); // Register components openApiDoc.Workspace.RegisterComponents(openApiDoc); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs index 6ceae13e3..67cb19ecb 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs @@ -17,30 +17,30 @@ internal static partial class OpenApiV3Deserializer { { "contentType", - (o, n) => o.ContentType = n.GetScalarValue() + (o, n, _) => o.ContentType = n.GetScalarValue() }, { "headers", - (o, n) => o.Headers = n.CreateMap(LoadHeader) + (o, n, t) => o.Headers = n.CreateMap(LoadHeader, t) }, { "style", - (o, n) => o.Style = n.GetScalarValue().GetEnumFromDisplayName() + (o, n, _) => o.Style = n.GetScalarValue().GetEnumFromDisplayName() }, { "explode", - (o, n) => o.Explode = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Explode = bool.Parse(n.GetScalarValue()) }, { "allowedReserved", - (o, n) => o.AllowReserved = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.AllowReserved = bool.Parse(n.GetScalarValue()) }, }; private static readonly PatternFieldMap _encodingPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiEncoding LoadEncoding(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs index 95d9584f3..a73ee02b1 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.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.Linq; @@ -19,26 +19,26 @@ internal static partial class OpenApiV3Deserializer { { "summary", - (o, n) => o.Summary = n.GetScalarValue() + (o, n, _) => o.Summary = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "value", - (o, n) => o.Value = n.CreateAny() + (o, n, _) => o.Value = n.CreateAny() }, { "externalValue", - (o, n) => o.ExternalValue = n.GetScalarValue() + (o, n, _) => o.ExternalValue = n.GetScalarValue() }, }; private static readonly PatternFieldMap _examplePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs index a4e52c35e..39712494c 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs @@ -20,18 +20,18 @@ internal static partial class OpenApiV3Deserializer // $ref { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "url", - (o, n) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, }; private static readonly PatternFieldMap _externalDocsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument = null) @@ -40,7 +40,7 @@ public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocume var externalDocs = new OpenApiExternalDocs(); - ParseMap(mapNode, externalDocs, _externalDocsFixedFields, _externalDocsPatternFields); + ParseMap(mapNode, externalDocs, _externalDocsFixedFields, _externalDocsPatternFields, hostDocument); return externalDocs; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs index d83f791f9..bc09b9b10 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.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.Linq; @@ -19,49 +19,49 @@ internal static partial class OpenApiV3Deserializer { { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "required", - (o, n) => o.Required = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Required = bool.Parse(n.GetScalarValue()) }, { "deprecated", - (o, n) => o.Deprecated = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Deprecated = bool.Parse(n.GetScalarValue()) }, { "allowEmptyValue", - (o, n) => o.AllowEmptyValue = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.AllowEmptyValue = bool.Parse(n.GetScalarValue()) }, { "allowReserved", - (o, n) => o.AllowReserved = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.AllowReserved = bool.Parse(n.GetScalarValue()) }, { "style", - (o, n) => o.Style = n.GetScalarValue().GetEnumFromDisplayName() + (o, n, _) => o.Style = n.GetScalarValue().GetEnumFromDisplayName() }, { "explode", - (o, n) => o.Explode = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Explode = bool.Parse(n.GetScalarValue()) }, { "schema", - (o, n) => o.Schema = LoadSchema(n) + (o, n, t) => o.Schema = LoadSchema(n, t) }, { "examples", - (o, n) => o.Examples = n.CreateMap(LoadExample) + (o, n, t) => o.Examples = n.CreateMap(LoadExample, t) }, { "example", - (o, n) => o.Example = n.CreateAny() + (o, n, _) => o.Example = n.CreateAny() }, }; private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs index fe44291f8..dcbf5ba4b 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs @@ -18,40 +18,40 @@ internal static partial class OpenApiV3Deserializer { { "title", - (o, n) => o.Title = n.GetScalarValue() + (o, n, _) => o.Title = n.GetScalarValue() }, { "version", - (o, n) => o.Version = n.GetScalarValue() + (o, n, _) => o.Version = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "termsOfService", - (o, n) => o.TermsOfService = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.TermsOfService = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { "contact", - (o, n) => o.Contact = LoadContact(n) + (o, n, t) => o.Contact = LoadContact(n, t) }, { "license", - (o, n) => o.License = LoadLicense(n) + (o, n, t) => o.License = LoadLicense(n, t) } }; public static readonly PatternFieldMap InfoPatternFields = new() { - {s => s.StartsWith("x-"), (o, k, n) => o.AddExtension(k,LoadExtension(k, n))} + {s => s.StartsWith("x-"), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument = null) { var mapNode = node.CheckMapNode("Info"); var info = new OpenApiInfo(); - ParseMap(mapNode, info, InfoFixedFields, InfoPatternFields); + ParseMap(mapNode, info, InfoFixedFields, InfoPatternFields, hostDocument); return info; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs index ab48c2b9e..e9054a0dd 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs @@ -18,17 +18,17 @@ internal static partial class OpenApiV3Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { "url", - (o, n) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.Url = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, }; private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument = null) @@ -37,7 +37,7 @@ internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostD var license = new OpenApiLicense(); - ParseMap(mapNode, license, _licenseFixedFields, _licensePatternFields); + ParseMap(mapNode, license, _licenseFixedFields, _licensePatternFields, hostDocument); return license; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs index 02c696de4..a95b6ebf8 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.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.Linq; @@ -19,30 +19,30 @@ internal static partial class OpenApiV3Deserializer { { "operationRef", - (o, n) => o.OperationRef = n.GetScalarValue() + (o, n, _) => o.OperationRef = n.GetScalarValue() }, { "operationId", - (o, n) => o.OperationId = n.GetScalarValue() + (o, n, _) => o.OperationId = n.GetScalarValue() }, { "parameters", - (o, n) => o.Parameters = n.CreateSimpleMap(LoadRuntimeExpressionAnyWrapper) + (o, n, _) => o.Parameters = n.CreateSimpleMap(LoadRuntimeExpressionAnyWrapper) }, { "requestBody", - (o, n) => o.RequestBody = LoadRuntimeExpressionAnyWrapper(n) + (o, n, _) => o.RequestBody = LoadRuntimeExpressionAnyWrapper(n) }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, - {"server", (o, n) => o.Server = LoadServer(n)} + {"server", (o, n, t) => o.Server = LoadServer(n, t)} }; private static readonly PatternFieldMap _linkPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static OpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument = null) @@ -57,7 +57,7 @@ public static OpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument return new OpenApiLinkReference(reference.Item1, hostDocument, reference.Item2); } - ParseMap(mapNode, link, _linkFixedFields, _linkPatternFields); + ParseMap(mapNode, link, _linkFixedFields, _linkPatternFields, hostDocument); return link; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs index 8e19f753b..1c055293a 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs @@ -18,26 +18,26 @@ internal static partial class OpenApiV3Deserializer { { OpenApiConstants.Schema, - (o, n) => o.Schema = LoadSchema(n) + (o, n, t) => o.Schema = LoadSchema(n, t) }, { OpenApiConstants.Examples, - (o, n) => o.Examples = n.CreateMap(LoadExample) + (o, n, t) => o.Examples = n.CreateMap(LoadExample, t) }, { OpenApiConstants.Example, - (o, n) => o.Example = n.CreateAny() + (o, n, _) => o.Example = n.CreateAny() }, { OpenApiConstants.Encoding, - (o, n) => o.Encoding = n.CreateMap(LoadEncoding) + (o, n, t) => o.Encoding = n.CreateMap(LoadEncoding, t) }, }; private static readonly PatternFieldMap _mediaTypePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _mediaTypeAnyFields = new() @@ -69,7 +69,7 @@ public static OpenApiMediaType LoadMediaType(ParseNode node, OpenApiDocument hos var mapNode = node.CheckMapNode(OpenApiConstants.Content); var mediaType = new OpenApiMediaType(); - ParseMap(mapNode, mediaType, _mediaTypeFixedFields, _mediaTypePatternFields); + ParseMap(mapNode, mediaType, _mediaTypeFixedFields, _mediaTypePatternFields, hostDocument); ProcessAnyFields(mapNode, mediaType, _mediaTypeAnyFields); ProcessAnyMapFields(mapNode, mediaType, _mediaTypeAnyMapOpenApiExampleFields); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs index be6615e39..8e8783efa 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs @@ -19,23 +19,23 @@ internal static partial class OpenApiV3Deserializer { { "authorizationUrl", - (o, n) => o.AuthorizationUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.AuthorizationUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { "tokenUrl", - (o, n) => o.TokenUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.TokenUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { "refreshUrl", - (o, n) => o.RefreshUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.RefreshUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, - {"scopes", (o, n) => o.Scopes = n.CreateSimpleMap(LoadString)} + {"scopes", (o, n, _) => o.Scopes = n.CreateSimpleMap(LoadString)} }; private static readonly PatternFieldMap _oAuthFlowPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlow LoadOAuthFlow(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs index 74bdc56df..2856be979 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs @@ -16,16 +16,16 @@ internal static partial class OpenApiV3Deserializer private static readonly FixedFieldMap _oAuthFlowsFixedFields = new() { - {"implicit", (o, n) => o.Implicit = LoadOAuthFlow(n)}, - {"password", (o, n) => o.Password = LoadOAuthFlow(n)}, - {"clientCredentials", (o, n) => o.ClientCredentials = LoadOAuthFlow(n)}, - {"authorizationCode", (o, n) => o.AuthorizationCode = LoadOAuthFlow(n)} + {"implicit", (o, n, t) => o.Implicit = LoadOAuthFlow(n, t)}, + {"password", (o, n, t) => o.Password = LoadOAuthFlow(n, t)}, + {"clientCredentials", (o, n, t) => o.ClientCredentials = LoadOAuthFlow(n, t)}, + {"authorizationCode", (o, n, t) => o.AuthorizationCode = LoadOAuthFlow(n, t)} }; private static readonly PatternFieldMap _oAuthFlowsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlows LoadOAuthFlows(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs index 3d3933bba..33aadc141 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.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 Microsoft.OpenApi.Extensions; @@ -18,7 +18,7 @@ internal static partial class OpenApiV3Deserializer new() { { - "tags", (o, n) => o.Tags = n.CreateSimpleList( + "tags", (o, n, doc) => o.Tags = n.CreateSimpleList( (valueNode, doc) => LoadTagByReference( valueNode.Context, @@ -26,54 +26,54 @@ internal static partial class OpenApiV3Deserializer }, { "summary", - (o, n) => o.Summary = n.GetScalarValue() + (o, n, _) => o.Summary = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "externalDocs", - (o, n) => o.ExternalDocs = LoadExternalDocs(n) + (o, n, _) => o.ExternalDocs = LoadExternalDocs(n) }, { "operationId", - (o, n) => o.OperationId = n.GetScalarValue() + (o, n, _) => o.OperationId = n.GetScalarValue() }, { "parameters", - (o, n) => o.Parameters = n.CreateList(LoadParameter) + (o, n, t) => o.Parameters = n.CreateList(LoadParameter, t) }, { "requestBody", - (o, n) => o.RequestBody = LoadRequestBody(n) + (o, n, t) => o.RequestBody = LoadRequestBody(n, t) }, { "responses", - (o, n) => o.Responses = LoadResponses(n) + (o, n, t) => o.Responses = LoadResponses(n, t) }, { "callbacks", - (o, n) => o.Callbacks = n.CreateMap(LoadCallback) + (o, n, t) => o.Callbacks = n.CreateMap(LoadCallback, t) }, { "deprecated", - (o, n) => o.Deprecated = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Deprecated = bool.Parse(n.GetScalarValue()) }, { "security", - (o, n) => o.Security = n.CreateList(LoadSecurityRequirement) + (o, n, t) => o.Security = n.CreateList(LoadSecurityRequirement, t) }, { "servers", - (o, n) => o.Servers = n.CreateList(LoadServer) + (o, n, t) => o.Servers = n.CreateList(LoadServer, t) }, }; private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument = null) @@ -82,7 +82,7 @@ internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument h var operation = new OpenApiOperation(); - ParseMap(mapNode, operation, _operationFixedFields, _operationPatternFields); + ParseMap(mapNode, operation, _operationFixedFields, _operationPatternFields, hostDocument); return operation; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs index 6c8a7772b..0446c52b7 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.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; @@ -21,10 +21,10 @@ internal static partial class OpenApiV3Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n,_) => o.Name = n.GetScalarValue() }, { - "in", (o, n) => + "in", (o, n, _) => { var inString = n.GetScalarValue(); @@ -35,54 +35,54 @@ internal static partial class OpenApiV3Deserializer }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "required", - (o, n) => o.Required = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Required = bool.Parse(n.GetScalarValue()) }, { "deprecated", - (o, n) => o.Deprecated = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Deprecated = bool.Parse(n.GetScalarValue()) }, { "allowEmptyValue", - (o, n) => o.AllowEmptyValue = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.AllowEmptyValue = bool.Parse(n.GetScalarValue()) }, { "allowReserved", - (o, n) => o.AllowReserved = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.AllowReserved = bool.Parse(n.GetScalarValue()) }, { "style", - (o, n) => o.Style = n.GetScalarValue().GetEnumFromDisplayName() + (o, n, _) => o.Style = n.GetScalarValue().GetEnumFromDisplayName() }, { "explode", - (o, n) => o.Explode = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Explode = bool.Parse(n.GetScalarValue()) }, { "schema", - (o, n) => o.Schema = LoadSchema(n) + (o, n, t) => o.Schema = LoadSchema(n, t) }, { "content", - (o, n) => o.Content = n.CreateMap(LoadMediaType) + (o, n, t) => o.Content = n.CreateMap(LoadMediaType, t) }, { "examples", - (o, n) => o.Examples = n.CreateMap(LoadExample) + (o, n, t) => o.Examples = n.CreateMap(LoadExample, t) }, { "example", - (o, n) => o.Example = n.CreateAny() + (o, n, _) => o.Example = n.CreateAny() }, }; private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _parameterAnyFields = new() @@ -122,7 +122,7 @@ public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hos var parameter = new OpenApiParameter(); - ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields); + ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields, hostDocument); ProcessAnyFields(mapNode, parameter, _parameterAnyFields); ProcessAnyMapFields(mapNode, parameter, _parameterAnyMapOpenApiExampleFields); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs index 7593ae162..afcee89b5 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.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.Linq; @@ -18,35 +18,35 @@ internal static partial class OpenApiV3Deserializer private static readonly FixedFieldMap _pathItemFixedFields = new() { { - "$ref", (o,n) => { + "$ref", (o, n, _) => { o.Reference = new() { ExternalResource = n.GetScalarValue() }; o.UnresolvedReference =true; } }, { "summary", - (o, n) => o.Summary = n.GetScalarValue() + (o, n, _) => o.Summary = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (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)} + {"get", (o, n, t) => o.AddOperation(OperationType.Get, LoadOperation(n, t))}, + {"put", (o, n, t) => o.AddOperation(OperationType.Put, LoadOperation(n, t))}, + {"post", (o, n, t) => o.AddOperation(OperationType.Post, LoadOperation(n, t))}, + {"delete", (o, n, t) => o.AddOperation(OperationType.Delete, LoadOperation(n, t))}, + {"options", (o, n, t) => o.AddOperation(OperationType.Options, LoadOperation(n, t))}, + {"head", (o, n, t) => o.AddOperation(OperationType.Head, LoadOperation(n, t))}, + {"patch", (o, n, t) => o.AddOperation(OperationType.Patch, LoadOperation(n, t))}, + {"trace", (o, n, t) => o.AddOperation(OperationType.Trace, LoadOperation(n, t))}, + {"servers", (o, n, t) => o.Servers = n.CreateList(LoadServer, t)}, + {"parameters", (o, n, t) => o.Parameters = n.CreateList(LoadParameter, t)} }; private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument = null) @@ -62,7 +62,7 @@ public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostD var pathItem = new OpenApiPathItem(); - ParseMap(mapNode, pathItem, _pathItemFixedFields, _pathItemPatternFields); + ParseMap(mapNode, pathItem, _pathItemFixedFields, _pathItemPatternFields, hostDocument); return pathItem; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs index 92451fe39..d4343973c 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs @@ -17,8 +17,8 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n) => o.Add(k, LoadPathItem(n))}, - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument = null) @@ -27,7 +27,7 @@ public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocumen var domainObject = new OpenApiPaths(); - ParseMap(mapNode, domainObject, _pathsFixedFields, _pathsPatternFields); + ParseMap(mapNode, domainObject, _pathsFixedFields, _pathsPatternFields, hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs index c9ddfef61..435b576e1 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.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.Linq; @@ -20,22 +20,22 @@ internal static partial class OpenApiV3Deserializer { { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "content", - (o, n) => o.Content = n.CreateMap(LoadMediaType) + (o, n, t) => o.Content = n.CreateMap(LoadMediaType, t) }, { "required", - (o, n) => o.Required = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Required = bool.Parse(n.GetScalarValue()) }, }; private static readonly PatternFieldMap _requestBodyPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument= null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs index 417f82dbd..e65a1aafe 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.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.Linq; @@ -19,26 +19,26 @@ internal static partial class OpenApiV3Deserializer { { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "headers", - (o, n) => o.Headers = n.CreateMap(LoadHeader) + (o, n, t) => o.Headers = n.CreateMap(LoadHeader, t) }, { "content", - (o, n) => o.Content = n.CreateMap(LoadMediaType) + (o, n, t) => o.Content = n.CreateMap(LoadMediaType, t) }, { "links", - (o, n) => o.Links = n.CreateMap(LoadLink) + (o, n, t) => o.Links = n.CreateMap(LoadLink, t) } }; private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument = null) @@ -53,7 +53,7 @@ public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostD } var response = new OpenApiResponse(); - ParseMap(mapNode, response, _responseFixedFields, _responsePatternFields); + ParseMap(mapNode, response, _responseFixedFields, _responsePatternFields, hostDocument); return response; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs index e9c0d54f3..817cdcbf6 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs @@ -17,8 +17,8 @@ internal static partial class OpenApiV3Deserializer public static readonly PatternFieldMap ResponsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n) => o.Add(p, LoadResponse(n))}, - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hostDocument = null) @@ -27,7 +27,7 @@ public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hos var domainObject = new OpenApiResponses(); - ParseMap(mapNode, domainObject, ResponsesFixedFields, ResponsesPatternFields); + ParseMap(mapNode, domainObject, ResponsesFixedFields, ResponsesPatternFields, hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs index 1ae954e5f..4a794408a 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.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; @@ -21,42 +21,42 @@ internal static partial class OpenApiV3Deserializer { { "type", - (o, n) => o.Type = n.GetScalarValue().GetEnumFromDisplayName() + (o, n, _) => o.Type = n.GetScalarValue().GetEnumFromDisplayName() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { "in", - (o, n) => o.In = n.GetScalarValue().GetEnumFromDisplayName() + (o, n, _) => o.In = n.GetScalarValue().GetEnumFromDisplayName() }, { "scheme", - (o, n) => o.Scheme = n.GetScalarValue() + (o, n, _) => o.Scheme = n.GetScalarValue() }, { "bearerFormat", - (o, n) => o.BearerFormat = n.GetScalarValue() + (o, n, _) => o.BearerFormat = n.GetScalarValue() }, { "openIdConnectUrl", - (o, n) => o.OpenIdConnectUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) + (o, n, _) => o.OpenIdConnectUrl = new(n.GetScalarValue(), UriKind.RelativeOrAbsolute) }, { "flows", - (o, n) => o.Flows = LoadOAuthFlows(n) + (o, n, t) => o.Flows = LoadOAuthFlows(n, t) } }; private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs index 80f7dbf49..9f56f764c 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs @@ -17,21 +17,21 @@ internal static partial class OpenApiV3Deserializer { { "url", - (o, n) => o.Url = n.GetScalarValue() + (o, n, _) => o.Url = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { "variables", - (o, n) => o.Variables = n.CreateMap(LoadServerVariable) + (o, n, t) => o.Variables = n.CreateMap(LoadServerVariable, t) } }; private static readonly PatternFieldMap _serverPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocument = null) @@ -40,7 +40,7 @@ public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocum var server = new OpenApiServer(); - ParseMap(mapNode, server, _serverFixedFields, _serverPatternFields); + ParseMap(mapNode, server, _serverFixedFields, _serverPatternFields, hostDocument); return server; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs index 7ba5e79cd..1bfa4fe04 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs @@ -18,22 +18,22 @@ internal static partial class OpenApiV3Deserializer { { "enum", - (o, n) => o.Enum = n.CreateSimpleList((s, p) => s.GetScalarValue()) + (o, n, _) => o.Enum = n.CreateSimpleList((s, p) => s.GetScalarValue()) }, { "default", - (o, n) => o.Default = n.GetScalarValue() + (o, n, _) => o.Default = n.GetScalarValue() }, { "description", - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, }; private static readonly PatternFieldMap _serverVariablePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDocument hostDocument = null) @@ -42,7 +42,7 @@ public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDo var serverVariable = new OpenApiServerVariable(); - ParseMap(mapNode, serverVariable, _serverVariableFixedFields, _serverVariablePatternFields); + ParseMap(mapNode, serverVariable, _serverVariableFixedFields, _serverVariablePatternFields, hostDocument); return serverVariable; } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs index 5b56ab8ca..218399cbb 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs @@ -17,21 +17,21 @@ internal static partial class OpenApiV3Deserializer { { OpenApiConstants.Name, - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { OpenApiConstants.Description, - (o, n) => o.Description = n.GetScalarValue() + (o, n, _) => o.Description = n.GetScalarValue() }, { OpenApiConstants.ExternalDocs, - (o, n) => o.ExternalDocs = LoadExternalDocs(n) + (o, n, t) => o.ExternalDocs = LoadExternalDocs(n, t) } }; private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs index 24f900dcd..eccb25daa 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs @@ -23,7 +23,8 @@ private static void ParseMap( MapNode mapNode, T domainObject, FixedFieldMap fixedFieldMap, - PatternFieldMap patternFieldMap) + PatternFieldMap patternFieldMap, + OpenApiDocument hostDocument = null) { if (mapNode == null) { @@ -32,7 +33,7 @@ private static void ParseMap( foreach (var propertyNode in mapNode) { - propertyNode.ParseField(domainObject, fixedFieldMap, patternFieldMap); + propertyNode.ParseField(domainObject, fixedFieldMap, patternFieldMap, hostDocument); } } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs index e72753b68..b57b641c4 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs @@ -18,30 +18,30 @@ internal static partial class OpenApiV3Deserializer { { "name", - (o, n) => o.Name = n.GetScalarValue() + (o, n, _) => o.Name = n.GetScalarValue() }, { "namespace", - (o, n) => o.Namespace = new(n.GetScalarValue(), UriKind.Absolute) + (o, n, _) => o.Namespace = new(n.GetScalarValue(), UriKind.Absolute) }, { "prefix", - (o, n) => o.Prefix = n.GetScalarValue() + (o, n, _) => o.Prefix = n.GetScalarValue() }, { "attribute", - (o, n) => o.Attribute = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Attribute = bool.Parse(n.GetScalarValue()) }, { "wrapped", - (o, n) => o.Wrapped = bool.Parse(n.GetScalarValue()) + (o, n, _) => o.Wrapped = bool.Parse(n.GetScalarValue()) }, }; private static readonly PatternFieldMap _xmlPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs index df705a7c9..50a41601b 100644 --- a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs @@ -1,13 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System.Collections.Generic; -using System.Globalization; -using System.Text.Json.Nodes; -using Json.Schema; -using Json.Schema.OpenApi; -using Microsoft.OpenApi.Extensions; -using Microsoft.OpenApi.Interfaces; +using System.Text.Json; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using JsonSchema = Json.Schema.JsonSchema; @@ -19,294 +13,10 @@ namespace Microsoft.OpenApi.Reader.V31 /// runtime Open API object model. /// internal static partial class OpenApiV31Deserializer - { - 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(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "exclusiveMaximum", (o, n) => - { - o.ExclusiveMaximum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "minimum", (o, n) => - { - o.Minimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "exclusiveMinimum", (o, n) => - { - o.ExclusiveMinimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "maxLength", (o, n) => - { - o.MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "minLength", (o, n) => - { - o.MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "pattern", (o, n) => - { - o.Pattern(n.GetScalarValue()); - } - }, - { - "maxItems", (o, n) => - { - o.MaxItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "minItems", (o, n) => - { - o.MinItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "uniqueItems", (o, n) => - { - o.UniqueItems(bool.Parse(n.GetScalarValue())); - } - }, - { - "maxProperties", (o, n) => - { - o.MaxProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "minProperties", (o, n) => - { - o.MinProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "required", (o, n) => - { - o.Required(new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))); - } - }, - { - "enum", (o, n) => - { - o.Enum(n.CreateListOfAny()); - } - }, - { - "type", (o, n) => - { - if(n is ListNode) - { - o.Type(n.CreateSimpleList((s, p) => SchemaTypeConverter.ConvertToSchemaValueType(s.GetScalarValue()))); - } - else - { - o.Type(SchemaTypeConverter.ConvertToSchemaValueType(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)); - } - }, - { - "patternProperties", (o, n) => - { - o.PatternProperties(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().Node); - } - }, - { - "discriminator", (o, n) => - { - var discriminator = LoadDiscriminator(n); - o.Discriminator(discriminator); - } - }, - { - "readOnly", (o, n) => - { - o.ReadOnly(bool.Parse(n.GetScalarValue())); - } - }, - { - "writeOnly", (o, n) => - { - o.WriteOnly(bool.Parse(n.GetScalarValue())); - } - }, - { - "xml", (o, n) => - { - var xml = LoadXml(n); - o.Xml(xml.Namespace, xml.Name, xml.Prefix, xml.Attribute, xml.Wrapped, - (IReadOnlyDictionary)xml.Extensions); - } - }, - { - "externalDocs", (o, n) => - { - var externalDocs = LoadExternalDocs(n); - o.ExternalDocs(externalDocs.Url, externalDocs.Description, - (IReadOnlyDictionary)externalDocs.Extensions); - } - }, - { - "example", (o, n) => - { - o.Example(n.CreateAny().Node); - } - }, - { - "examples", (o, n) => - { - o.Examples(n.CreateSimpleList((s, p) =>(JsonNode) s.GetScalarValue())); - } - }, - { - "deprecated", (o, n) => - { - o.Deprecated(bool.Parse(n.GetScalarValue())); - } - }, - }; - - private static readonly PatternFieldMap _schemaPatternFields = new PatternFieldMap - { - {s => s.StartsWith("x-"), (o, p, n) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} - }; - + { public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument = null) { - var mapNode = node.CheckMapNode(OpenApiConstants.Schema); - var builder = new JsonSchemaBuilder(); - - // check for a $ref and if present, add it to the builder as a Ref keyword - var pointer = mapNode.GetReferencePointer(); - if (pointer != null) - { - builder = builder.Ref(pointer); - - // Check for summary and description and append to builder - var summary = mapNode.GetSummaryValue(); - var description = mapNode.GetDescriptionValue(); - if (!string.IsNullOrEmpty(summary)) - { - builder.Summary(summary); - } - if (!string.IsNullOrEmpty(description)) - { - builder.Description(description); - } - - return builder.Build(); - } - - foreach (var propertyNode in mapNode) - { - propertyNode.ParseField(builder, _schemaFixedFields, _schemaPatternFields); - } - - var schema = builder.Build(); - return schema; - } - - private static Dictionary LoadExtensions(string value, IOpenApiExtension extension) - { - var extensions = new Dictionary - { - { value, extension } - }; - return extensions; + return JsonSerializer.Deserialize(node.JsonNode); } } - } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs index 4689bc837..580ce1356 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs @@ -1,4 +1,4 @@ -using Microsoft.OpenApi.Expressions; +using Microsoft.OpenApi.Expressions; using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; @@ -20,8 +20,8 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _callbackPatternFields = new() { - {s => !s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n))}, - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}, + {s => !s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, + {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static OpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument = null) @@ -36,7 +36,7 @@ public static OpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostD var domainObject = new OpenApiCallback(); - ParseMap(mapNode, domainObject, _callbackFixedFields, _callbackPatternFields); + ParseMap(mapNode, domainObject, _callbackFixedFields, _callbackPatternFields, hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs index 278c2043e..a9c543813 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs @@ -17,22 +17,22 @@ internal static partial class OpenApiV31Deserializer { private static readonly FixedFieldMap _componentsFixedFields = new() { - {"schemas", (o, n) => o.Schemas = n.CreateMap(LoadSchema)}, - {"responses", (o, n) => o.Responses = n.CreateMap(LoadResponse)}, - {"parameters", (o, n) => o.Parameters = n.CreateMap(LoadParameter)}, - {"examples", (o, n) => o.Examples = n.CreateMap(LoadExample)}, - {"requestBodies", (o, n) => o.RequestBodies = n.CreateMap(LoadRequestBody)}, - {"headers", (o, n) => o.Headers = n.CreateMap(LoadHeader)}, - {"securitySchemes", (o, n) => o.SecuritySchemes = n.CreateMap(LoadSecurityScheme)}, - {"links", (o, n) => o.Links = n.CreateMap(LoadLink)}, - {"callbacks", (o, n) => o.Callbacks = n.CreateMap(LoadCallback)}, - {"pathItems", (o, n) => o.PathItems = n.CreateMap(LoadPathItem)} + {"schemas", (o, n, t) => o.Schemas = n.CreateMap(LoadSchema, t)}, + {"responses", (o, n, t) => o.Responses = n.CreateMap(LoadResponse, t)}, + {"parameters", (o, n, t) => o.Parameters = n.CreateMap(LoadParameter, t)}, + {"examples", (o, n, t) => o.Examples = n.CreateMap(LoadExample, t)}, + {"requestBodies", (o, n, t) => o.RequestBodies = n.CreateMap(LoadRequestBody, t)}, + {"headers", (o, n, t) => o.Headers = n.CreateMap(LoadHeader, t)}, + {"securitySchemes", (o, n, t) => o.SecuritySchemes = n.CreateMap(LoadSecurityScheme, t)}, + {"links", (o, n, t) => o.Links = n.CreateMap(LoadLink, t)}, + {"callbacks", (o, n, t) => o.Callbacks = n.CreateMap(LoadCallback, t)}, + {"pathItems", (o, n, t) => o.PathItems = n.CreateMap(LoadPathItem, t)} }; private static readonly PatternFieldMap _componentsPatternFields = new() { - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument hostDocument = null) @@ -40,7 +40,7 @@ public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument h var mapNode = node.CheckMapNode("components"); var components = new OpenApiComponents(); - ParseMap(mapNode, components, _componentsFixedFields, _componentsPatternFields); + ParseMap(mapNode, components, _componentsFixedFields, _componentsPatternFields, hostDocument); return components; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs index 71e673ee0..7434deeec 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs @@ -14,19 +14,19 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _contactFixedFields = new() { { - "name", (o, n) => + "name", (o, n, _) => { o.Name = n.GetScalarValue(); } }, { - "email", (o, n) => + "email", (o, n, _) => { o.Email = n.GetScalarValue(); } }, { - "url", (o, n) => + "url", (o, n, _) => { o.Url = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } @@ -35,7 +35,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument = null) @@ -43,7 +43,7 @@ public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDoc var mapNode = node as MapNode; var contact = new OpenApiContact(); - ParseMap(mapNode, contact, _contactFixedFields, _contactPatternFields); + ParseMap(mapNode, contact, _contactFixedFields, _contactPatternFields, hostDocument); return contact; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs index 7c04dcdc8..51122a9c8 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs @@ -14,13 +14,13 @@ internal static partial class OpenApiV31Deserializer new() { { - "propertyName", (o, n) => + "propertyName", (o, n, _) => { o.PropertyName = n.GetScalarValue(); } }, { - "mapping", (o, n) => + "mapping", (o, n, _) => { o.Mapping = n.CreateSimpleMap(LoadString); } @@ -30,10 +30,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _discriminatorPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiDiscriminator LoadDiscriminator(ParseNode node) + public static OpenApiDiscriminator LoadDiscriminator(ParseNode node, OpenApiDocument hostDocument = null) { var mapNode = node.CheckMapNode("discriminator"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs index e4de78613..8137fb460 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs @@ -15,17 +15,17 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _openApiFixedFields = new() { { - "openapi", (o, n) => + "openapi", (o, n, _) => { } /* Version is valid field but we already parsed it */ }, - {"info", (o, n) => o.Info = LoadInfo(n)}, - {"jsonSchemaDialect", (o, n) => o.JsonSchemaDialect = n.GetScalarValue() }, - {"servers", (o, n) => o.Servers = n.CreateList(LoadServer)}, - {"paths", (o, n) => o.Paths = LoadPaths(n)}, - {"webhooks", (o, n) => o.Webhooks = n.CreateMap(LoadPathItem)}, - {"components", (o, n) => o.Components = LoadComponents(n)}, - {"tags", (o, n) => {o.Tags = n.CreateList(LoadTag); + {"info", (o, n, _) => o.Info = LoadInfo(n, o)}, + {"jsonSchemaDialect", (o, n, _) => o.JsonSchemaDialect = n.GetScalarValue() }, + {"servers", (o, n, _) => o.Servers = n.CreateList(LoadServer, o)}, + {"paths", (o, n, _) => o.Paths = LoadPaths(n, o)}, + {"webhooks", (o, n, _) => o.Webhooks = n.CreateMap(LoadPathItem, o)}, + {"components", (o, n, _) => o.Components = LoadComponents(n, o)}, + {"tags", (o, n, _) => {o.Tags = n.CreateList(LoadTag, o); foreach (var tag in o.Tags) { tag.Reference = new OpenApiReference() @@ -35,14 +35,14 @@ internal static partial class OpenApiV31Deserializer }; } } }, - {"externalDocs", (o, n) => o.ExternalDocs = LoadExternalDocs(n)}, - {"security", (o, n) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement)} + {"externalDocs", (o, n, _) => o.ExternalDocs = LoadExternalDocs(n, o)}, + {"security", (o, n, _) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement, o)} }; private static readonly 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))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiDocument LoadOpenApi(RootNode rootNode) @@ -50,7 +50,7 @@ public static OpenApiDocument LoadOpenApi(RootNode rootNode) var openApiDoc = new OpenApiDocument(); var openApiNode = rootNode.GetMap(); - ParseMap(openApiNode, openApiDoc, _openApiFixedFields, _openApiPatternFields); + ParseMap(openApiNode, openApiDoc, _openApiFixedFields, _openApiPatternFields, openApiDoc); // Register components openApiDoc.Workspace.RegisterComponents(openApiDoc); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs index c97057ded..b54c5e75b 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs @@ -13,31 +13,31 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _encodingFixedFields = new() { { - "contentType", (o, n) => + "contentType", (o, n, _) => { o.ContentType = n.GetScalarValue(); } }, { - "headers", (o, n) => + "headers", (o, n, t) => { - o.Headers = n.CreateMap(LoadHeader); + o.Headers = n.CreateMap(LoadHeader, t); } }, { - "style", (o, n) => + "style", (o, n, _) => { o.Style = n.GetScalarValue().GetEnumFromDisplayName(); } }, { - "explode", (o, n) => + "explode", (o, n, _) => { o.Explode = bool.Parse(n.GetScalarValue()); } }, { - "allowedReserved", (o, n) => + "allowedReserved", (o, n, _) => { o.AllowReserved = bool.Parse(n.GetScalarValue()); } @@ -47,7 +47,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _encodingPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiEncoding LoadEncoding(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs index 87b7f1e88..0035360d5 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -15,25 +15,25 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _exampleFixedFields = new() { { - "summary", (o, n) => + "summary", (o, n, _) => { o.Summary = n.GetScalarValue(); } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "value", (o, n) => + "value", (o, n, _) => { o.Value = n.CreateAny(); } }, { - "externalValue", (o, n) => + "externalValue", (o, n, _) => { o.ExternalValue = n.GetScalarValue(); } @@ -44,7 +44,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _examplePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs index 825e9007d..f42288fcf 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs @@ -16,13 +16,13 @@ internal static partial class OpenApiV31Deserializer { // $ref { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "url", (o, n) => + "url", (o, n, _) => { o.Url = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } @@ -33,7 +33,7 @@ internal static partial class OpenApiV31Deserializer new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument = null) @@ -42,7 +42,7 @@ public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocume var externalDocs = new OpenApiExternalDocs(); - ParseMap(mapNode, externalDocs, _externalDocsFixedFields, _externalDocsPatternFields); + ParseMap(mapNode, externalDocs, _externalDocsFixedFields, _externalDocsPatternFields, hostDocument); return externalDocs; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs index 5d7130aa8..d3657db02 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -15,61 +15,61 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _headerFixedFields = new() { { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "required", (o, n) => + "required", (o, n, _) => { o.Required = bool.Parse(n.GetScalarValue()); } }, { - "deprecated", (o, n) => + "deprecated", (o, n, _) => { o.Deprecated = bool.Parse(n.GetScalarValue()); } }, { - "allowEmptyValue", (o, n) => + "allowEmptyValue", (o, n, _) => { o.AllowEmptyValue = bool.Parse(n.GetScalarValue()); } }, { - "allowReserved", (o, n) => + "allowReserved", (o, n, _) => { o.AllowReserved = bool.Parse(n.GetScalarValue()); } }, { - "style", (o, n) => + "style", (o, n, _) => { o.Style = n.GetScalarValue().GetEnumFromDisplayName(); } }, { - "explode", (o, n) => + "explode", (o, n, _) => { o.Explode = bool.Parse(n.GetScalarValue()); } }, { - "schema", (o, n) => + "schema", (o, n, t) => { - o.Schema = LoadSchema(n); + o.Schema = LoadSchema(n, t); } }, { - "examples", (o, n) => + "examples", (o, n, t) => { - o.Examples = n.CreateMap(LoadExample); + o.Examples = n.CreateMap(LoadExample, t); } }, { - "example", (o, n) => + "example", (o, n, _) => { o.Example = n.CreateAny(); } @@ -78,7 +78,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs index 5b9a61029..6476e1acc 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs @@ -14,59 +14,59 @@ internal static partial class OpenApiV31Deserializer public static readonly FixedFieldMap InfoFixedFields = new() { { - "title", (o, n) => + "title", (o, n, _) => { o.Title = n.GetScalarValue(); } }, { - "version", (o, n) => + "version", (o, n, _) => { o.Version = n.GetScalarValue(); } }, { - "summary", (o, n) => + "summary", (o, n, _) => { o.Summary = n.GetScalarValue(); } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "termsOfService", (o, n) => + "termsOfService", (o, n, _) => { o.TermsOfService = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } }, { - "contact", (o, n) => + "contact", (o, n, t) => { - o.Contact = LoadContact(n); + o.Contact = LoadContact(n, t); } }, { - "license", (o, n) => + "license", (o, n, t) => { - o.License = LoadLicense(n); + o.License = LoadLicense(n, t); } } }; public static readonly PatternFieldMap InfoPatternFields = new() { - {s => s.StartsWith("x-"), (o, k, n) => o.AddExtension(k,LoadExtension(k, n))} + {s => s.StartsWith("x-"), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument = null) { var mapNode = node.CheckMapNode("Info"); var info = new OpenApiInfo(); - ParseMap(mapNode, info, InfoFixedFields, InfoPatternFields); + ParseMap(mapNode, info, InfoFixedFields, InfoPatternFields, hostDocument); return info; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs index 52534f70a..efddbc2b1 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs @@ -14,19 +14,19 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _licenseFixedFields = new() { { - "name", (o, n) => + "name", (o, n, _) => { o.Name = n.GetScalarValue(); } }, { - "identifier", (o, n) => + "identifier", (o, n, _) => { o.Identifier = n.GetScalarValue(); } }, { - "url", (o, n) => + "url", (o, n, _) => { o.Url = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } @@ -35,7 +35,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument = null) @@ -44,7 +44,7 @@ internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostD var license = new OpenApiLicense(); - ParseMap(mapNode, license, _licenseFixedFields, _licensePatternFields); + ParseMap(mapNode, license, _licenseFixedFields, _licensePatternFields, hostDocument); return license; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs index 05dc90ca9..aa1e26ea1 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -15,41 +15,41 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _linkFixedFields = new() { { - "operationRef", (o, n) => + "operationRef", (o, n, _) => { o.OperationRef = n.GetScalarValue(); } }, { - "operationId", (o, n) => + "operationId", (o, n, _) => { o.OperationId = n.GetScalarValue(); } }, { - "parameters", (o, n) => + "parameters", (o, n, _) => { o.Parameters = n.CreateSimpleMap(LoadRuntimeExpressionAnyWrapper); } }, { - "requestBody", (o, n) => + "requestBody", (o, n, _) => { o.RequestBody = LoadRuntimeExpressionAnyWrapper(n); } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, - {"server", (o, n) => o.Server = LoadServer(n)} + {"server", (o, n, t) => o.Server = LoadServer(n, t)} }; private static readonly PatternFieldMap _linkPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static OpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument = null) @@ -64,7 +64,7 @@ public static OpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument return new OpenApiLinkReference(reference.Item1, hostDocument, reference.Item2); } - ParseMap(mapNode, link, _linkFixedFields, _linkPatternFields); + ParseMap(mapNode, link, _linkFixedFields, _linkPatternFields, hostDocument); return link; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs index 7645deead..c0ce9b843 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs @@ -14,27 +14,27 @@ internal static partial class OpenApiV31Deserializer new() { { - OpenApiConstants.Schema, (o, n) => + OpenApiConstants.Schema, (o, n, t) => { - o.Schema = LoadSchema(n); + o.Schema = LoadSchema(n, t); } }, { - OpenApiConstants.Examples, (o, n) => + OpenApiConstants.Examples, (o, n, t) => { - o.Examples = n.CreateMap(LoadExample); + o.Examples = n.CreateMap(LoadExample, t); } }, { - OpenApiConstants.Example, (o, n) => + OpenApiConstants.Example, (o, n, _) => { o.Example = n.CreateAny(); } }, { - OpenApiConstants.Encoding, (o, n) => + OpenApiConstants.Encoding, (o, n, t) => { - o.Encoding = n.CreateMap(LoadEncoding); + o.Encoding = n.CreateMap(LoadEncoding, t); } }, }; @@ -42,7 +42,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _mediaTypePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _mediaTypeAnyFields = new AnyFieldMap @@ -76,7 +76,7 @@ public static OpenApiMediaType LoadMediaType(ParseNode node, OpenApiDocument hos var mediaType = new OpenApiMediaType(); - ParseMap(mapNode, mediaType, _mediaTypeFixedFields, _mediaTypePatternFields); + ParseMap(mapNode, mediaType, _mediaTypeFixedFields, _mediaTypePatternFields, hostDocument); ProcessAnyFields(mapNode, mediaType, _mediaTypeAnyFields); ProcessAnyMapFields(mapNode, mediaType, _mediaTypeAnyMapOpenApiExampleFields); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs index 975e0272b..199cf14e7 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs @@ -15,30 +15,30 @@ internal static partial class OpenApiV31Deserializer new() { { - "authorizationUrl", (o, n) => + "authorizationUrl", (o, n, _) => { o.AuthorizationUrl = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } }, { - "tokenUrl", (o, n) => + "tokenUrl", (o, n, _) => { o.TokenUrl = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } }, { - "refreshUrl", (o, n) => + "refreshUrl", (o, n, _) => { o.RefreshUrl = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } }, - {"scopes", (o, n) => o.Scopes = n.CreateSimpleMap(LoadString)} + {"scopes", (o, n, _) => o.Scopes = n.CreateSimpleMap(LoadString)} }; private static readonly PatternFieldMap _oAuthFlowPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlow LoadOAuthFlow(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs index 6c0b16223..28316ec9b 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs @@ -13,16 +13,16 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _oAuthFlowsFixedFileds = new() { - {"implicit", (o, n) => o.Implicit = LoadOAuthFlow(n)}, - {"password", (o, n) => o.Password = LoadOAuthFlow(n)}, - {"clientCredentials", (o, n) => o.ClientCredentials = LoadOAuthFlow(n)}, - {"authorizationCode", (o, n) => o.AuthorizationCode = LoadOAuthFlow(n)} + {"implicit", (o, n, t) => o.Implicit = LoadOAuthFlow(n, t)}, + {"password", (o, n, t) => o.Password = LoadOAuthFlow(n, t)}, + {"clientCredentials", (o, n, t) => o.ClientCredentials = LoadOAuthFlow(n, t)}, + {"authorizationCode", (o, n, t) => o.AuthorizationCode = LoadOAuthFlow(n, t)} }; private static readonly PatternFieldMap _oAuthFlowsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlows LoadOAuthFlows(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs index 2143ffb65..fb143e4c6 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs @@ -1,4 +1,4 @@ -using Microsoft.OpenApi.Extensions; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -15,74 +15,74 @@ internal static partial class OpenApiV31Deserializer new() { { - "tags", (o, n) => o.Tags = n.CreateSimpleList( + "tags", (o, n, doc) => o.Tags = n.CreateSimpleList( (valueNode, doc) => LoadTagByReference(valueNode.GetScalarValue(), doc)) }, { - "summary", (o, n) => + "summary", (o, n, _) => { o.Summary = n.GetScalarValue(); } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "externalDocs", (o, n) => + "externalDocs", (o, n, t) => { - o.ExternalDocs = LoadExternalDocs(n); + o.ExternalDocs = LoadExternalDocs(n, t); } }, { - "operationId", (o, n) => + "operationId", (o, n, _) => { o.OperationId = n.GetScalarValue(); } }, { - "parameters", (o, n) => + "parameters", (o, n, t) => { - o.Parameters = n.CreateList(LoadParameter); + o.Parameters = n.CreateList(LoadParameter, t); } }, { - "requestBody", (o, n) => + "requestBody", (o, n, t) => { - o.RequestBody = LoadRequestBody(n); + o.RequestBody = LoadRequestBody(n, t); } }, { - "responses", (o, n) => + "responses", (o, n, t) => { - o.Responses = LoadResponses(n); + o.Responses = LoadResponses(n, t); } }, { - "callbacks", (o, n) => + "callbacks", (o, n, t) => { - o.Callbacks = n.CreateMap(LoadCallback); + o.Callbacks = n.CreateMap(LoadCallback, t); } }, { - "deprecated", (o, n) => + "deprecated", (o, n, _) => { o.Deprecated = bool.Parse(n.GetScalarValue()); } }, { - "security", (o, n) => + "security", (o, n, t) => { - o.Security = n.CreateList(LoadSecurityRequirement); + o.Security = n.CreateList(LoadSecurityRequirement, t); } }, { - "servers", (o, n) => + "servers", (o, n, t) => { - o.Servers = n.CreateList(LoadServer); + o.Servers = n.CreateList(LoadServer, t); } }, }; @@ -90,7 +90,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument = null) @@ -99,7 +99,7 @@ internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument h var operation = new OpenApiOperation(); - ParseMap(mapNode, operation, _operationFixedFields, _operationPatternFields); + ParseMap(mapNode, operation, _operationFixedFields, _operationPatternFields, hostDocument); return operation; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs index 8c4c200d8..e8f4e5a93 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; @@ -17,13 +17,13 @@ internal static partial class OpenApiV31Deserializer new() { { - "name", (o, n) => + "name", (o, n, _) => { o.Name = n.GetScalarValue(); } }, { - "in", (o, n) => + "in", (o, n, _) => { var inString = n.GetScalarValue(); o.In = Enum.GetValues(typeof(ParameterLocation)).Cast() @@ -33,67 +33,67 @@ internal static partial class OpenApiV31Deserializer } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "required", (o, n) => + "required", (o, n, _) => { o.Required = bool.Parse(n.GetScalarValue()); } }, { - "deprecated", (o, n) => + "deprecated", (o, n, _) => { o.Deprecated = bool.Parse(n.GetScalarValue()); } }, { - "allowEmptyValue", (o, n) => + "allowEmptyValue", (o, n, _) => { o.AllowEmptyValue = bool.Parse(n.GetScalarValue()); } }, { - "allowReserved", (o, n) => + "allowReserved", (o, n, _) => { o.AllowReserved = bool.Parse(n.GetScalarValue()); } }, { - "style", (o, n) => + "style", (o, n, _) => { o.Style = n.GetScalarValue().GetEnumFromDisplayName(); } }, { - "explode", (o, n) => + "explode", (o, n, _) => { o.Explode = bool.Parse(n.GetScalarValue()); } }, { - "schema", (o, n) => + "schema", (o, n, t) => { - o.Schema = LoadSchema(n); + o.Schema = LoadSchema(n, t); } }, { - "content", (o, n) => + "content", (o, n, t) => { - o.Content = n.CreateMap(LoadMediaType); + o.Content = n.CreateMap(LoadMediaType, t); } }, { - "examples", (o, n) => + "examples", (o, n, t) => { - o.Examples = n.CreateMap(LoadExample); + o.Examples = n.CreateMap(LoadExample, t); } }, { - "example", (o, n) => + "example", (o, n, _) => { o.Example = n.CreateAny(); } @@ -103,7 +103,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _parameterAnyFields = new AnyFieldMap @@ -143,7 +143,7 @@ public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hos var parameter = new OpenApiParameter(); - ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields); + ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields, hostDocument); ProcessAnyFields(mapNode, parameter, _parameterAnyFields); ProcessAnyMapFields(mapNode, parameter, _parameterAnyMapOpenApiExampleFields); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs index 2aadfb03e..8797b03e6 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -16,39 +16,39 @@ internal static partial class OpenApiV31Deserializer { { - "$ref", (o,n) => { + "$ref", (o,n, _) => { o.Reference = new OpenApiReference() { ExternalResource = n.GetScalarValue() }; o.UnresolvedReference =true; } }, { - "summary", (o, n) => + "summary", (o, n, _) => { o.Summary = n.GetScalarValue(); } }, { - "description", (o, n) => + "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)} + {"get", (o, n, t) => o.AddOperation(OperationType.Get, LoadOperation(n, t))}, + {"put", (o, n, t) => o.AddOperation(OperationType.Put, LoadOperation(n, t))}, + {"post", (o, n, t) => o.AddOperation(OperationType.Post, LoadOperation(n, t))}, + {"delete", (o, n, t) => o.AddOperation(OperationType.Delete, LoadOperation(n, t))}, + {"options", (o, n, t) => o.AddOperation(OperationType.Options, LoadOperation(n, t))}, + {"head", (o, n, t) => o.AddOperation(OperationType.Head, LoadOperation(n, t))}, + {"patch", (o, n, t) => o.AddOperation(OperationType.Patch, LoadOperation(n, t))}, + {"trace", (o, n, t) => o.AddOperation(OperationType.Trace, LoadOperation(n, t))}, + {"servers", (o, n, t) => o.Servers = n.CreateList(LoadServer, t)}, + {"parameters", (o, n, t) => o.Parameters = n.CreateList(LoadParameter, t)} }; private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument = null) @@ -65,7 +65,7 @@ public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostD var pathItem = new OpenApiPathItem(); - ParseMap(mapNode, pathItem, _pathItemFixedFields, _pathItemPatternFields); + ParseMap(mapNode, pathItem, _pathItemFixedFields, _pathItemPatternFields, hostDocument); return pathItem; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs index 640f6fc90..e9fef44a8 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs @@ -14,8 +14,8 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n) => o.Add(k, LoadPathItem(n))}, - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument = null) @@ -24,7 +24,7 @@ public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocumen var domainObject = new OpenApiPaths(); - ParseMap(mapNode, domainObject, _pathsFixedFields, _pathsPatternFields); + ParseMap(mapNode, domainObject, _pathsFixedFields, _pathsPatternFields, hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs index 22e5fedb4..7acea65c0 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -16,19 +16,19 @@ internal static partial class OpenApiV31Deserializer new() { { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "content", (o, n) => + "content", (o, n, t) => { - o.Content = n.CreateMap(LoadMediaType); + o.Content = n.CreateMap(LoadMediaType, t); } }, { - "required", (o, n) => + "required", (o, n, _) => { o.Required = bool.Parse(n.GetScalarValue()); } @@ -38,7 +38,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _requestBodyPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs index d1fba99be..611574bf2 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -15,27 +15,27 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _responseFixedFields = new() { { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "headers", (o, n) => + "headers", (o, n, t) => { - o.Headers = n.CreateMap(LoadHeader); + o.Headers = n.CreateMap(LoadHeader, t); } }, { - "content", (o, n) => + "content", (o, n, t) => { - o.Content = n.CreateMap(LoadMediaType); + o.Content = n.CreateMap(LoadMediaType, t); } }, { - "links", (o, n) => + "links", (o, n, t) => { - o.Links = n.CreateMap(LoadLink); + o.Links = n.CreateMap(LoadLink, t); } } }; @@ -43,7 +43,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument = null) @@ -58,7 +58,7 @@ public static OpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostD } var response = new OpenApiResponse(); - ParseMap(mapNode, response, _responseFixedFields, _responsePatternFields); + ParseMap(mapNode, response, _responseFixedFields, _responsePatternFields, hostDocument); return response; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs index ef1e9a3d2..42cb3b826 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs @@ -17,8 +17,8 @@ internal static partial class OpenApiV31Deserializer public static readonly PatternFieldMap ResponsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n) => o.Add(p, LoadResponse(n))}, - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hostDocument = null) @@ -27,7 +27,7 @@ public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hos var domainObject = new OpenApiResponses(); - ParseMap(mapNode, domainObject, ResponsesFixedFields, ResponsesPatternFields); + ParseMap(mapNode, domainObject, ResponsesFixedFields, ResponsesPatternFields, hostDocument); return domainObject; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs index 399eaf704..7b5ff5cb8 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.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; @@ -20,51 +20,51 @@ internal static partial class OpenApiV31Deserializer new() { { - "type", (o, n) => + "type", (o, n, _) => { o.Type = n.GetScalarValue().GetEnumFromDisplayName(); } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "name", (o, n) => + "name", (o, n, _) => { o.Name = n.GetScalarValue(); } }, { - "in", (o, n) => + "in", (o, n, _) => { o.In = n.GetScalarValue().GetEnumFromDisplayName(); } }, { - "scheme", (o, n) => + "scheme", (o, n, _) => { o.Scheme = n.GetScalarValue(); } }, { - "bearerFormat", (o, n) => + "bearerFormat", (o, n, _) => { o.BearerFormat = n.GetScalarValue(); } }, { - "openIdConnectUrl", (o, n) => + "openIdConnectUrl", (o, n, _) => { o.OpenIdConnectUrl = new Uri(n.GetScalarValue(), UriKind.RelativeOrAbsolute); } }, { - "flows", (o, n) => + "flows", (o, n, t) => { - o.Flows = LoadOAuthFlows(n); + o.Flows = LoadOAuthFlows(n, t); } } }; @@ -72,7 +72,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs index a6c932dd9..efe25fedb 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs @@ -16,28 +16,28 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _serverFixedFields = new() { { - "url", (o, n) => + "url", (o, n, _) => { o.Url = n.GetScalarValue(); } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - "variables", (o, n) => + "variables", (o, n, t) => { - o.Variables = n.CreateMap(LoadServerVariable); + o.Variables = n.CreateMap(LoadServerVariable, t); } } }; private static readonly PatternFieldMap _serverPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocument = null) @@ -46,7 +46,7 @@ public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocum var server = new OpenApiServer(); - ParseMap(mapNode, server, _serverFixedFields, _serverPatternFields); + ParseMap(mapNode, server, _serverFixedFields, _serverPatternFields, hostDocument); return server; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs index aa3ce48d9..e5344554d 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs @@ -17,19 +17,19 @@ internal static partial class OpenApiV31Deserializer new() { { - "enum", (o, n) => + "enum", (o, n, _) => { o.Enum = n.CreateSimpleList((s, p) => s.GetScalarValue()); } }, { - "default", (o, n) => + "default", (o, n, _) => { o.Default = n.GetScalarValue(); } }, { - "description", (o, n) => + "description", (o, n, _) => { o.Description = n.GetScalarValue(); } @@ -39,7 +39,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _serverVariablePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDocument hostDocument = null) @@ -48,7 +48,7 @@ public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDo var serverVariable = new OpenApiServerVariable(); - ParseMap(mapNode, serverVariable, _serverVariableFixedFields, _serverVariablePatternFields); + ParseMap(mapNode, serverVariable, _serverVariableFixedFields, _serverVariablePatternFields, hostDocument); return serverVariable; } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs index 76f3e674e..a6dfe5f1f 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs @@ -16,28 +16,28 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _tagFixedFields = new() { { - OpenApiConstants.Name, (o, n) => + OpenApiConstants.Name, (o, n, _) => { o.Name = n.GetScalarValue(); } }, { - OpenApiConstants.Description, (o, n) => + OpenApiConstants.Description, (o, n, _) => { o.Description = n.GetScalarValue(); } }, { - OpenApiConstants.ExternalDocs, (o, n) => + OpenApiConstants.ExternalDocs, (o, n, t) => { - o.ExternalDocs = LoadExternalDocs(n); + o.ExternalDocs = LoadExternalDocs(n, t); } } }; private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument = null) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs index b65711e29..aa38c326d 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs @@ -23,7 +23,8 @@ private static void ParseMap( MapNode mapNode, T domainObject, FixedFieldMap fixedFieldMap, - PatternFieldMap patternFieldMap) + PatternFieldMap patternFieldMap, + OpenApiDocument doc = null) { if (mapNode == null) { @@ -32,7 +33,7 @@ private static void ParseMap( foreach (var propertyNode in mapNode) { - propertyNode.ParseField(domainObject, fixedFieldMap, patternFieldMap); + propertyNode.ParseField(domainObject, fixedFieldMap, patternFieldMap, doc); } } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs index 38b8b38fe..4c7a17b85 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs @@ -17,31 +17,31 @@ internal static partial class OpenApiV31Deserializer private static readonly FixedFieldMap _xmlFixedFields = new FixedFieldMap { { - "name", (o, n) => + "name", (o, n, _) => { o.Name = n.GetScalarValue(); } }, { - "namespace", (o, n) => + "namespace", (o, n, _) => { o.Namespace = new Uri(n.GetScalarValue(), UriKind.Absolute); } }, { - "prefix", (o, n) => + "prefix", (o, n, _) => { o.Prefix = n.GetScalarValue(); } }, { - "attribute", (o, n) => + "attribute", (o, n, _) => { o.Attribute = bool.Parse(n.GetScalarValue()); } }, { - "wrapped", (o, n) => + "wrapped", (o, n, _) => { o.Wrapped = bool.Parse(n.GetScalarValue()); } @@ -51,7 +51,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _xmlPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument = null) diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index ecd680642..b070c6289 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -1075,6 +1075,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatch() var warnings = result.OpenApiDiagnostic.Warnings; Assert.False(warnings.Any()); } + [Fact] public void ParseDocWithRefsUsingProxyReferencesSucceeds() { From 7f5d24cb3312bcf184a72475aae8304207abda87 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 15:00:02 +0300 Subject: [PATCH 16/29] Register the host document with the schema registry for reference resolution --- .../Validations/Rules/RuleHelpers.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index ba8a8926c..e57d67a89 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -49,16 +49,14 @@ public static void ValidateDataTypeMismatch( { if (schema is not null) { - if (context.HostDocument != null) - { - var visitor = new JsonSchemaReferenceResolver(context.HostDocument); - var walker = new OpenApiWalker(visitor); - schema = walker.Walk(schema); - } - var options = new EvaluationOptions(); options.OutputFormat = OutputFormat.List; + if (context.HostDocument != null) + { + options.SchemaRegistry.Register(context.HostDocument.BaseUri, context.HostDocument); + } + var results = schema.Evaluate(value, options); if (!results.IsValid) From ff38301dd77143d346bff82acf85602bd29b3e46 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 15:00:54 +0300 Subject: [PATCH 17/29] Implement FindSubschema by fetching the referenced schema from our components registry --- src/Microsoft.OpenApi/Models/OpenApiDocument.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 78ef581ed..e39d285a5 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -676,7 +676,8 @@ public static ReadResult Parse(string input, /// public JsonSchema FindSubschema(Json.Pointer.JsonPointer pointer, EvaluationOptions options) { - throw new NotImplementedException(); + var locationUri = string.Concat(BaseUri, pointer); + return (JsonSchema)Workspace.ResolveReference(locationUri); } } From dcc7b7f00ae5dae05372bcdc9c9721b5bad976dd Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 15:01:03 +0300 Subject: [PATCH 18/29] Fix failing tests --- .../Validations/OpenApiHeaderValidationTests.cs | 10 +++++----- .../Validations/OpenApiMediaTypeValidationTests.cs | 12 +++++------- .../Validations/OpenApiParameterValidationTests.cs | 14 +++++++------- .../Validations/OpenApiSchemaValidationTests.cs | 12 ++++++------ 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs index 62c56b430..d9397a933 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.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.Collections.Generic; @@ -109,15 +109,15 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { "type : Value is \"string\" but should be \"object\" at ", - "type : Value is \"string\" but should be \"integer\" at /y", + "type : Value is \"string\" but should be \"integer\" at /y", "type : Value is \"string\" but should be \"integer\" at /z", "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { - "#/examples/example0/value", - "#/examples/example1/value", - "#/examples/example1/value", + "#/examples/example0/value", + "#/examples/example1/value", + "#/examples/example1/value", "#/examples/example2/value" }); } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs index 3886de28e..a9ef6ec25 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.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.Collections.Generic; @@ -104,18 +104,16 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - "type : Value is \"string\" but should be \"object\" at ", + "type : Value is \"string\" but should be \"object\" at ", "type : Value is \"string\" but should be \"integer\" at /y", - "type : Value is \"string\" but should be \"integer\" at /z", + "type : Value is \"string\" but should be \"integer\" at /z", "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { - // #enum/0 is not an error since the spec allows - // representing an object using a string. "#/examples/example0/value", - "#/examples/example1/value", - "#/examples/example1/value", + "#/examples/example1/value", + "#/examples/example1/value", "#/examples/example2/value" }); } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs index c21f1bc16..3f7a2d20c 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.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; @@ -160,18 +160,18 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - "type : Value is \"string\" but should be \"object\" at ", - "type : Value is \"string\" but should be \"integer\" at /y", - "type : Value is \"string\" but should be \"integer\" at /z", + "type : Value is \"string\" but should be \"object\" at ", + "type : Value is \"string\" but should be \"integer\" at /y", + "type : Value is \"string\" but should be \"integer\" at /z", "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { // #enum/0 is not an error since the spec allows // representing an object using a string. - "#/{parameter1}/examples/example0/value", - "#/{parameter1}/examples/example1/value", - "#/{parameter1}/examples/example1/value", + "#/{parameter1}/examples/example0/value", + "#/{parameter1}/examples/example1/value", + "#/{parameter1}/examples/example1/value", "#/{parameter1}/examples/example2/value" }); } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs index e4da87e3a..b5491c40c 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.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; @@ -116,16 +116,16 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() result.Should().BeFalse(); warnings.Select(e => e.Message).Should().BeEquivalentTo(new[] { - "type : Value is \"string\" but should be \"object\" at ", - "type : Value is \"string\" but should be \"integer\" at /y", - "type : Value is \"string\" but should be \"integer\" at /z", + "type : Value is \"string\" but should be \"object\" at ", + "type : Value is \"string\" but should be \"integer\" at /y", + "type : Value is \"string\" but should be \"integer\" at /z", "type : Value is \"array\" but should be \"object\" at " }); warnings.Select(e => e.Pointer).Should().BeEquivalentTo(new[] { "#/enum/0", - "#/enum/1", - "#/enum/1", + "#/enum/1", + "#/enum/1", "#/enum/2" }); } From babc887a1794f66febf9f835157048395bbce77f Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 15:32:50 +0300 Subject: [PATCH 19/29] Set the new schema's baseUri to match the document's --- src/Microsoft.OpenApi/Services/OpenApiWalker.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index ef3ea811d..223dc09e2 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -18,6 +18,7 @@ namespace Microsoft.OpenApi.Services /// public class OpenApiWalker { + private static OpenApiDocument HostDocument; private readonly OpenApiVisitorBase _visitor; private readonly Stack _schemaLoop = new Stack(); private readonly Stack _pathItemLoop = new Stack(); @@ -41,6 +42,7 @@ public void Walk(OpenApiDocument doc) return; } + HostDocument = doc; _schemaLoop.Clear(); _pathItemLoop.Clear(); @@ -900,6 +902,7 @@ internal JsonSchema Walk(JsonSchema schema, bool isComponent = false) Walk(key, () => newSchema = Walk(item.Value)); props.Add(key, newSchema); schema = builder.Properties(props); + schema.BaseUri = HostDocument.BaseUri; } }); } From d6593ab06af1293ff2d7563f10b32f1df779b2cf Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 15:50:36 +0300 Subject: [PATCH 20/29] Refactor V2 schema deserializer to update the referenceable schema's baseUri to match that of the document --- src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs index f9ff3fc26..176593c94 100644 --- a/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/JsonSchemaDeserializer.cs @@ -234,7 +234,13 @@ public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument var pointer = mapNode.GetReferencePointer(); if (pointer != null) { - return schemaBuilder.Ref(pointer); + var jsonSchema = schemaBuilder.Ref(pointer).Build(); + if (hostDocument != null) + { + jsonSchema.BaseUri = hostDocument.BaseUri; + } + + return jsonSchema; } foreach (var propertyNode in mapNode) From 0fb689dba98be93428966360c4b31e0577266b5d Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 15:51:03 +0300 Subject: [PATCH 21/29] Register the OpenApi-based vocabs --- src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs index 50a41601b..4eb361ab9 100644 --- a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.Text.Json; +using Json.Schema.OpenApi; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using JsonSchema = Json.Schema.JsonSchema; @@ -16,6 +17,7 @@ internal static partial class OpenApiV31Deserializer { public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument = null) { + Vocabularies.Register(); return JsonSerializer.Deserialize(node.JsonNode); } } From 85a2b548db1b12ea8c3cdf16d70b33d944e98ea3 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 18:24:17 +0300 Subject: [PATCH 22/29] Add a null check --- src/Microsoft.OpenApi/Services/OpenApiWalker.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index 223dc09e2..5a2666711 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -902,7 +902,10 @@ internal JsonSchema Walk(JsonSchema schema, bool isComponent = false) Walk(key, () => newSchema = Walk(item.Value)); props.Add(key, newSchema); schema = builder.Properties(props); - schema.BaseUri = HostDocument.BaseUri; + if (HostDocument != null) + { + schema.BaseUri = HostDocument.BaseUri; + } } }); } From b09eb624cabc334a7e648bfc1bfe69a994fa62b2 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 29 Apr 2024 18:25:17 +0300 Subject: [PATCH 23/29] Revert the V31 deserializer --- .../Reader/V31/JsonSchemaDeserializer.cs | 292 +++++++++++++++++- 1 file changed, 289 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs index 4eb361ab9..8db73d977 100644 --- a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs @@ -1,8 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System.Text.Json; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json.Nodes; +using Json.Schema; using Json.Schema.OpenApi; +using Microsoft.OpenApi.Extensions; +using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using JsonSchema = Json.Schema.JsonSchema; @@ -15,10 +20,291 @@ namespace Microsoft.OpenApi.Reader.V31 /// internal static partial class OpenApiV31Deserializer { + 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(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "exclusiveMaximum", (o, n, _) => + { + o.ExclusiveMaximum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "minimum", (o, n, _) => + { + o.Minimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "exclusiveMinimum", (o, n, _) => + { + o.ExclusiveMinimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "maxLength", (o, n, _) => + { + o.MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "minLength", (o, n, _) => + { + o.MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "pattern", (o, n, _) => + { + o.Pattern(n.GetScalarValue()); + } + }, + { + "maxItems", (o, n, _) => + { + o.MaxItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "minItems", (o, n, _) => + { + o.MinItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "uniqueItems", (o, n, _) => + { + o.UniqueItems(bool.Parse(n.GetScalarValue())); + } + }, + { + "maxProperties", (o, n, _) => + { + o.MaxProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "minProperties", (o, n, _) => + { + o.MinProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "required", (o, n, _) => + { + o.Required(new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))); + } + }, + { + "enum", (o, n, _) => + { + o.Enum(n.CreateListOfAny()); + } + }, + { + "type", (o, n, _) => + { + if(n is ListNode) + { + o.Type(n.CreateSimpleList((s, p) => SchemaTypeConverter.ConvertToSchemaValueType(s.GetScalarValue()))); + } + else + { + o.Type(SchemaTypeConverter.ConvertToSchemaValueType(n.GetScalarValue())); + } + } + }, + { + "allOf", (o, n, t) => + { + o.AllOf(n.CreateList(LoadSchema, t)); + } + }, + { + "oneOf", (o, n, t) => + { + o.OneOf(n.CreateList(LoadSchema, t)); + } + }, + { + "anyOf", (o, n, t) => + { + o.AnyOf(n.CreateList(LoadSchema, t)); + } + }, + { + "not", (o, n, t) => + { + o.Not(LoadSchema(n, t)); + } + }, + { + "items", (o, n, t) => + { + o.Items(LoadSchema(n, t)); + } + }, + { + "properties", (o, n, t) => + { + o.Properties(n.CreateMap(LoadSchema, t)); + } + }, + { + "patternProperties", (o, n, t) => + { + o.PatternProperties(n.CreateMap(LoadSchema, t)); + } + }, + { + "additionalProperties", (o, n, t) => + { + if (n is ValueNode) + { + o.AdditionalPropertiesAllowed(bool.Parse(n.GetScalarValue())); + } + else + { + o.AdditionalProperties(LoadSchema(n, t)); + } + } + }, + { + "description", (o, n, _) => + { + o.Description(n.GetScalarValue()); + } + }, + { + "format", (o, n, _) => + { + o.Format(n.GetScalarValue()); + } + }, + { + "default", (o, n, _) => + { + o.Default(n.CreateAny().Node); + } + }, + { + "discriminator", (o, n, t) => + { + var discriminator = LoadDiscriminator(n, t); + o.Discriminator(discriminator); + } + }, + { + "readOnly", (o, n, _) => + { + o.ReadOnly(bool.Parse(n.GetScalarValue())); + } + }, + { + "writeOnly", (o, n, _) => + { + o.WriteOnly(bool.Parse(n.GetScalarValue())); + } + }, + { + "xml", (o, n, t) => + { + var xml = LoadXml(n, t); + o.Xml(xml.Namespace, xml.Name, xml.Prefix, xml.Attribute, xml.Wrapped, + (IReadOnlyDictionary)xml.Extensions); + } + }, + { + "externalDocs", (o, n, t) => + { + var externalDocs = LoadExternalDocs(n, t); + o.ExternalDocs(externalDocs.Url, externalDocs.Description, + (IReadOnlyDictionary)externalDocs.Extensions); + } + }, + { + "example", (o, n, _) => + { + o.Example(n.CreateAny().Node); + } + }, + { + "examples", (o, n, _) => + { + o.Examples(n.CreateSimpleList((s, p) =>(JsonNode) s.GetScalarValue())); + } + }, + { + "deprecated", (o, n, _) => + { + o.Deprecated(bool.Parse(n.GetScalarValue())); + } + }, + }; + + private static readonly PatternFieldMap _schemaPatternFields = new PatternFieldMap + { + {s => s.StartsWith("x-"), (o, p, n, _) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} + }; + public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument = null) { - Vocabularies.Register(); - return JsonSerializer.Deserialize(node.JsonNode); + var mapNode = node.CheckMapNode(OpenApiConstants.Schema); + var builder = new JsonSchemaBuilder(); + + // check for a $ref and if present, add it to the builder as a Ref keyword + var pointer = mapNode.GetReferencePointer(); + if (pointer != null) + { + var jsonSchema = builder.Ref(pointer).Build(); + if (hostDocument != null) + { + jsonSchema.BaseUri = hostDocument.BaseUri; + } + + return jsonSchema; + } + + foreach (var propertyNode in mapNode) + { + propertyNode.ParseField(builder, _schemaFixedFields, _schemaPatternFields); + } + + var schema = builder.Build(); + + if (hostDocument != null) + { + schema.BaseUri = hostDocument.BaseUri; + } + + return schema; + } + + private static Dictionary LoadExtensions(string value, IOpenApiExtension extension) + { + var extensions = new Dictionary + { + { value, extension } + }; + return extensions; } } + } From a278267ff3ce175e518ddc40c2824bba70f1b94e Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 30 Apr 2024 13:42:13 +0300 Subject: [PATCH 24/29] Use the extension method from JsonSchema.NET to get a dicriminator object from the schema and serialize it --- .../Formatters/PowerShellFormatter.cs | 4 ++-- .../Validations/Rules/JsonSchemaRules.cs | 4 ++-- .../Writers/OpenApiWriterBase.cs | 20 ++++++++++++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index aab3fb829..d8b19f916 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -348,9 +348,9 @@ private static JsonSchema CopySchema(JsonSchema schema, JsonSchema newSchema) { schemaBuilder.MinProperties(minProperties); } - if (schema.GetDiscriminator() == null && newSchema.GetOpenApiDiscriminator() is { } discriminator) + if (schema.GetDiscriminator() == null && newSchema.GetDiscriminator() is { } discriminator) { - schemaBuilder.Discriminator(discriminator); + schemaBuilder.Discriminator(discriminator.PropertyName, discriminator.Mapping, discriminator.Extensions); } if (schema.GetOpenApiExternalDocs() == null && newSchema.GetOpenApiExternalDocs() is { } externalDocs) { diff --git a/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs index 0443b9fb8..69be42de7 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs @@ -84,9 +84,9 @@ public static class JsonSchemaRules // discriminator context.Enter("discriminator"); - if (jsonSchema.GetRef() != null && jsonSchema.GetOpenApiDiscriminator() != null) + if (jsonSchema.GetRef() != null && jsonSchema.GetDiscriminator() != null) { - var discriminatorName = jsonSchema.GetOpenApiDiscriminator()?.PropertyName; + var discriminatorName = jsonSchema.GetDiscriminator()?.PropertyName; if (!ValidateChildSchemaAgainstDiscriminator(jsonSchema, discriminatorName)) { diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs index 542dc5cd4..5e965da9b 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs @@ -574,7 +574,25 @@ public void WriteJsonSchemaWithoutReference(IOpenApiWriter writer, JsonSchema sc writer.WriteProperty(OpenApiConstants.Nullable, schema.GetNullable(), false); // discriminator - writer.WriteOptionalObject(OpenApiConstants.Discriminator, schema.GetOpenApiDiscriminator(), (w, d) => d.SerializeAsV3(w)); + var discriminator = schema.GetDiscriminator(); + if (discriminator != null) + { + writer.WriteStartObject(); + + // propertyName + writer.WriteProperty(OpenApiConstants.PropertyName, discriminator.PropertyName); + + // mapping + writer.WriteOptionalMap(OpenApiConstants.Mapping, (IDictionary)discriminator.Mapping, (w, s) => w.WriteValue(s)); + + if (version == OpenApiSpecVersion.OpenApi3_1 && discriminator.Extensions.Any()) + { + // extensions + writer.WriteExtensions((IDictionary)discriminator.Extensions, OpenApiSpecVersion.OpenApi3_1); + } + + writer.WriteEndObject(); + } // readOnly writer.WriteProperty(OpenApiConstants.ReadOnly, schema.GetReadOnly(), false); From e93cd4c61a32380d50af9584fbf4cfcb536a3770 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 30 Apr 2024 13:57:47 +0300 Subject: [PATCH 25/29] Use System.Text to deserialize a node into a JSON schema --- .../Reader/V31/JsonSchemaDeserializer.cs | 292 +----------------- 1 file changed, 3 insertions(+), 289 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs index 8db73d977..4eb361ab9 100644 --- a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System.Collections.Generic; -using System.Globalization; -using System.Text.Json.Nodes; -using Json.Schema; +using System.Text.Json; using Json.Schema.OpenApi; -using Microsoft.OpenApi.Extensions; -using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using JsonSchema = Json.Schema.JsonSchema; @@ -20,291 +15,10 @@ namespace Microsoft.OpenApi.Reader.V31 /// internal static partial class OpenApiV31Deserializer { - 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(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "exclusiveMaximum", (o, n, _) => - { - o.ExclusiveMaximum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "minimum", (o, n, _) => - { - o.Minimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "exclusiveMinimum", (o, n, _) => - { - o.ExclusiveMinimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); - } - }, - { - "maxLength", (o, n, _) => - { - o.MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "minLength", (o, n, _) => - { - o.MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "pattern", (o, n, _) => - { - o.Pattern(n.GetScalarValue()); - } - }, - { - "maxItems", (o, n, _) => - { - o.MaxItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "minItems", (o, n, _) => - { - o.MinItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "uniqueItems", (o, n, _) => - { - o.UniqueItems(bool.Parse(n.GetScalarValue())); - } - }, - { - "maxProperties", (o, n, _) => - { - o.MaxProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "minProperties", (o, n, _) => - { - o.MinProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); - } - }, - { - "required", (o, n, _) => - { - o.Required(new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))); - } - }, - { - "enum", (o, n, _) => - { - o.Enum(n.CreateListOfAny()); - } - }, - { - "type", (o, n, _) => - { - if(n is ListNode) - { - o.Type(n.CreateSimpleList((s, p) => SchemaTypeConverter.ConvertToSchemaValueType(s.GetScalarValue()))); - } - else - { - o.Type(SchemaTypeConverter.ConvertToSchemaValueType(n.GetScalarValue())); - } - } - }, - { - "allOf", (o, n, t) => - { - o.AllOf(n.CreateList(LoadSchema, t)); - } - }, - { - "oneOf", (o, n, t) => - { - o.OneOf(n.CreateList(LoadSchema, t)); - } - }, - { - "anyOf", (o, n, t) => - { - o.AnyOf(n.CreateList(LoadSchema, t)); - } - }, - { - "not", (o, n, t) => - { - o.Not(LoadSchema(n, t)); - } - }, - { - "items", (o, n, t) => - { - o.Items(LoadSchema(n, t)); - } - }, - { - "properties", (o, n, t) => - { - o.Properties(n.CreateMap(LoadSchema, t)); - } - }, - { - "patternProperties", (o, n, t) => - { - o.PatternProperties(n.CreateMap(LoadSchema, t)); - } - }, - { - "additionalProperties", (o, n, t) => - { - if (n is ValueNode) - { - o.AdditionalPropertiesAllowed(bool.Parse(n.GetScalarValue())); - } - else - { - o.AdditionalProperties(LoadSchema(n, t)); - } - } - }, - { - "description", (o, n, _) => - { - o.Description(n.GetScalarValue()); - } - }, - { - "format", (o, n, _) => - { - o.Format(n.GetScalarValue()); - } - }, - { - "default", (o, n, _) => - { - o.Default(n.CreateAny().Node); - } - }, - { - "discriminator", (o, n, t) => - { - var discriminator = LoadDiscriminator(n, t); - o.Discriminator(discriminator); - } - }, - { - "readOnly", (o, n, _) => - { - o.ReadOnly(bool.Parse(n.GetScalarValue())); - } - }, - { - "writeOnly", (o, n, _) => - { - o.WriteOnly(bool.Parse(n.GetScalarValue())); - } - }, - { - "xml", (o, n, t) => - { - var xml = LoadXml(n, t); - o.Xml(xml.Namespace, xml.Name, xml.Prefix, xml.Attribute, xml.Wrapped, - (IReadOnlyDictionary)xml.Extensions); - } - }, - { - "externalDocs", (o, n, t) => - { - var externalDocs = LoadExternalDocs(n, t); - o.ExternalDocs(externalDocs.Url, externalDocs.Description, - (IReadOnlyDictionary)externalDocs.Extensions); - } - }, - { - "example", (o, n, _) => - { - o.Example(n.CreateAny().Node); - } - }, - { - "examples", (o, n, _) => - { - o.Examples(n.CreateSimpleList((s, p) =>(JsonNode) s.GetScalarValue())); - } - }, - { - "deprecated", (o, n, _) => - { - o.Deprecated(bool.Parse(n.GetScalarValue())); - } - }, - }; - - private static readonly PatternFieldMap _schemaPatternFields = new PatternFieldMap - { - {s => s.StartsWith("x-"), (o, p, n, _) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} - }; - public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument = null) { - var mapNode = node.CheckMapNode(OpenApiConstants.Schema); - var builder = new JsonSchemaBuilder(); - - // check for a $ref and if present, add it to the builder as a Ref keyword - var pointer = mapNode.GetReferencePointer(); - if (pointer != null) - { - var jsonSchema = builder.Ref(pointer).Build(); - if (hostDocument != null) - { - jsonSchema.BaseUri = hostDocument.BaseUri; - } - - return jsonSchema; - } - - foreach (var propertyNode in mapNode) - { - propertyNode.ParseField(builder, _schemaFixedFields, _schemaPatternFields); - } - - var schema = builder.Build(); - - if (hostDocument != null) - { - schema.BaseUri = hostDocument.BaseUri; - } - - return schema; - } - - private static Dictionary LoadExtensions(string value, IOpenApiExtension extension) - { - var extensions = new Dictionary - { - { value, extension } - }; - return extensions; + Vocabularies.Register(); + return JsonSerializer.Deserialize(node.JsonNode); } } - } From d1cb00205c6fd9ba1b5da73c5902430d3acfb439 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 2 May 2024 15:10:30 +0300 Subject: [PATCH 26/29] Replace Enumerable methods with indexing --- src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index d8b19f916..3e46b4181 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -205,7 +205,7 @@ private void AddAdditionalPropertiesToSchema(ref JsonSchema schema) private static JsonSchema ResolveOneOfSchema(ref JsonSchema schema) { - if (schema.GetOneOf()?.FirstOrDefault() is {} newSchema) + if (schema.GetOneOf()?[0] is {} newSchema) { var schemaBuilder = BuildSchema(schema); schemaBuilder = schemaBuilder.Remove("oneOf"); @@ -219,7 +219,7 @@ private static JsonSchema ResolveOneOfSchema(ref JsonSchema schema) private static JsonSchema ResolveAnyOfSchema(ref JsonSchema schema) { - if (schema.GetAnyOf()?.FirstOrDefault() is {} newSchema) + if (schema.GetAnyOf()?[0] is {} newSchema) { var schemaBuilder = BuildSchema(schema); schemaBuilder = schemaBuilder.Remove("anyOf"); From 5c96d1ced3b7b7eb8658a26d121663afcc10d9ba Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 2 May 2024 15:21:10 +0300 Subject: [PATCH 27/29] Exclude files from build --- .../Microsoft.OpenApi.Readers.Tests.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index 5491a10d1..d59c0d42b 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -6,11 +6,11 @@ ..\..\src\Microsoft.OpenApi.snk - + Always - - Always + + Always From 71c396326901c07e5321e1e79442387680d2fc24 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 2 May 2024 17:28:16 +0300 Subject: [PATCH 28/29] Revert code to fix failing tests --- .../Formatters/PowerShellFormatter.cs | 4 +- .../Reader/V31/JsonSchemaDeserializer.cs | 294 +++++++++++++++++- .../Validations/Rules/JsonSchemaRules.cs | 4 +- .../Writers/OpenApiWriterBase.cs | 20 +- 4 files changed, 296 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index 3e46b4181..d8b19f916 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -205,7 +205,7 @@ private void AddAdditionalPropertiesToSchema(ref JsonSchema schema) private static JsonSchema ResolveOneOfSchema(ref JsonSchema schema) { - if (schema.GetOneOf()?[0] is {} newSchema) + if (schema.GetOneOf()?.FirstOrDefault() is {} newSchema) { var schemaBuilder = BuildSchema(schema); schemaBuilder = schemaBuilder.Remove("oneOf"); @@ -219,7 +219,7 @@ private static JsonSchema ResolveOneOfSchema(ref JsonSchema schema) private static JsonSchema ResolveAnyOfSchema(ref JsonSchema schema) { - if (schema.GetAnyOf()?[0] is {} newSchema) + if (schema.GetAnyOf()?.FirstOrDefault() is {} newSchema) { var schemaBuilder = BuildSchema(schema); schemaBuilder = schemaBuilder.Remove("anyOf"); diff --git a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs index 4eb361ab9..02bf282a6 100644 --- a/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/JsonSchemaDeserializer.cs @@ -1,8 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System.Text.Json; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json.Nodes; +using Json.Schema; using Json.Schema.OpenApi; +using Microsoft.OpenApi.Extensions; +using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using JsonSchema = Json.Schema.JsonSchema; @@ -15,10 +20,293 @@ namespace Microsoft.OpenApi.Reader.V31 /// internal static partial class OpenApiV31Deserializer { + 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(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "exclusiveMaximum", (o, n, _) => + { + o.ExclusiveMaximum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "minimum", (o, n, _) => + { + o.Minimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "exclusiveMinimum", (o, n, _) => + { + o.ExclusiveMinimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + } + }, + { + "maxLength", (o, n, _) => + { + o.MaxLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "minLength", (o, n, _) => + { + o.MinLength(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "pattern", (o, n, _) => + { + o.Pattern(n.GetScalarValue()); + } + }, + { + "maxItems", (o, n, _) => + { + o.MaxItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "minItems", (o, n, _) => + { + o.MinItems(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "uniqueItems", (o, n, _) => + { + o.UniqueItems(bool.Parse(n.GetScalarValue())); + } + }, + { + "maxProperties", (o, n, _) => + { + o.MaxProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "minProperties", (o, n, _) => + { + o.MinProperties(uint.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + } + }, + { + "required", (o, n, _) => + { + o.Required(new HashSet(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))); + } + }, + { + "enum", (o, n, _) => + { + o.Enum(n.CreateListOfAny()); + } + }, + { + "type", (o, n, _) => + { + if(n is ListNode) + { + o.Type(n.CreateSimpleList((s, p) => SchemaTypeConverter.ConvertToSchemaValueType(s.GetScalarValue()))); + } + else + { + o.Type(SchemaTypeConverter.ConvertToSchemaValueType(n.GetScalarValue())); + } + } + }, + { + "allOf", (o, n, t) => + { + o.AllOf(n.CreateList(LoadSchema, t)); + } + }, + { + "oneOf", (o, n, t) => + { + o.OneOf(n.CreateList(LoadSchema, t)); + } + }, + { + "anyOf", (o, n, t) => + { + o.AnyOf(n.CreateList(LoadSchema, t)); + } + }, + { + "not", (o, n, t) => + { + o.Not(LoadSchema(n, t)); + } + }, + { + "items", (o, n, t) => + { + o.Items(LoadSchema(n, t)); + } + }, + { + "properties", (o, n, t) => + { + o.Properties(n.CreateMap(LoadSchema, t)); + } + }, + { + "patternProperties", (o, n, t) => + { + o.PatternProperties(n.CreateMap(LoadSchema, t)); + } + }, + { + "additionalProperties", (o, n, t) => + { + if (n is ValueNode) + { + o.AdditionalPropertiesAllowed(bool.Parse(n.GetScalarValue())); + } + else + { + o.AdditionalProperties(LoadSchema(n, t)); + } + } + }, + { + "description", (o, n, _) => + { + o.Description(n.GetScalarValue()); + } + }, + { + "format", (o, n, _) => + { + o.Format(n.GetScalarValue()); + } + }, + { + "default", (o, n, _) => + { + o.Default(n.CreateAny().Node); + } + }, + { + "discriminator", (o, n, t) => + { + var discriminator = LoadDiscriminator(n, t); + o.Discriminator(discriminator); + } + }, + { + "readOnly", (o, n, _) => + { + o.ReadOnly(bool.Parse(n.GetScalarValue())); + } + }, + { + "writeOnly", (o, n, _) => + { + o.WriteOnly(bool.Parse(n.GetScalarValue())); + } + }, + { + "xml", (o, n, t) => + { + var xml = LoadXml(n); + o.Xml(xml.Namespace, xml.Name, xml.Prefix, xml.Attribute, xml.Wrapped, + (IReadOnlyDictionary)xml.Extensions); + } + }, + { + "externalDocs", (o, n, t) => + { + var externalDocs = LoadExternalDocs(n, t); + o.ExternalDocs(externalDocs.Url, externalDocs.Description, + (IReadOnlyDictionary)externalDocs.Extensions); + } + }, + { + "example", (o, n, _) => + { + o.Example(n.CreateAny().Node); + } + }, + { + "examples", (o, n, _) => + { + o.Examples(n.CreateSimpleList((s, p) =>(JsonNode) s.GetScalarValue())); + } + }, + { + "deprecated", (o, n, _) => + { + o.Deprecated(bool.Parse(n.GetScalarValue())); + } + }, + }; + + private static readonly PatternFieldMap _schemaPatternFields = new PatternFieldMap + { + {s => s.StartsWith("x-"), (o, p, n, _) => o.Extensions(LoadExtensions(p, LoadExtension(p, n)))} + }; + public static JsonSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument = null) { - Vocabularies.Register(); - return JsonSerializer.Deserialize(node.JsonNode); + var mapNode = node.CheckMapNode(OpenApiConstants.Schema); + var builder = new JsonSchemaBuilder(); + + // check for a $ref and if present, add it to the builder as a Ref keyword + var pointer = mapNode.GetReferencePointer(); + if (pointer != null) + { + builder = builder.Ref(pointer); + + // Check for summary and description and append to builder + var summary = mapNode.GetSummaryValue(); + var description = mapNode.GetDescriptionValue(); + if (!string.IsNullOrEmpty(summary)) + { + builder.Summary(summary); + } + if (!string.IsNullOrEmpty(description)) + { + builder.Description(description); + } + + return builder.Build(); + } + + foreach (var propertyNode in mapNode) + { + propertyNode.ParseField(builder, _schemaFixedFields, _schemaPatternFields); + } + + var schema = builder.Build(); + return schema; + } + + private static Dictionary LoadExtensions(string value, IOpenApiExtension extension) + { + var extensions = new Dictionary + { + { value, extension } + }; + return extensions; } } + } diff --git a/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs index 69be42de7..0443b9fb8 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/JsonSchemaRules.cs @@ -84,9 +84,9 @@ public static class JsonSchemaRules // discriminator context.Enter("discriminator"); - if (jsonSchema.GetRef() != null && jsonSchema.GetDiscriminator() != null) + if (jsonSchema.GetRef() != null && jsonSchema.GetOpenApiDiscriminator() != null) { - var discriminatorName = jsonSchema.GetDiscriminator()?.PropertyName; + var discriminatorName = jsonSchema.GetOpenApiDiscriminator()?.PropertyName; if (!ValidateChildSchemaAgainstDiscriminator(jsonSchema, discriminatorName)) { diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs index 5e965da9b..542dc5cd4 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs @@ -574,25 +574,7 @@ public void WriteJsonSchemaWithoutReference(IOpenApiWriter writer, JsonSchema sc writer.WriteProperty(OpenApiConstants.Nullable, schema.GetNullable(), false); // discriminator - var discriminator = schema.GetDiscriminator(); - if (discriminator != null) - { - writer.WriteStartObject(); - - // propertyName - writer.WriteProperty(OpenApiConstants.PropertyName, discriminator.PropertyName); - - // mapping - writer.WriteOptionalMap(OpenApiConstants.Mapping, (IDictionary)discriminator.Mapping, (w, s) => w.WriteValue(s)); - - if (version == OpenApiSpecVersion.OpenApi3_1 && discriminator.Extensions.Any()) - { - // extensions - writer.WriteExtensions((IDictionary)discriminator.Extensions, OpenApiSpecVersion.OpenApi3_1); - } - - writer.WriteEndObject(); - } + writer.WriteOptionalObject(OpenApiConstants.Discriminator, schema.GetOpenApiDiscriminator(), (w, d) => d.SerializeAsV3(w)); // readOnly writer.WriteProperty(OpenApiConstants.ReadOnly, schema.GetReadOnly(), false); From d0380cee75daf489f1069f795b35a4af1234d4bd Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 2 May 2024 17:43:00 +0300 Subject: [PATCH 29/29] Remove static field modifier --- src/Microsoft.OpenApi/Services/OpenApiWalker.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index 5a2666711..b934074f9 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -18,7 +18,7 @@ namespace Microsoft.OpenApi.Services /// public class OpenApiWalker { - private static OpenApiDocument HostDocument; + private OpenApiDocument _hostDocument; private readonly OpenApiVisitorBase _visitor; private readonly Stack _schemaLoop = new Stack(); private readonly Stack _pathItemLoop = new Stack(); @@ -42,7 +42,7 @@ public void Walk(OpenApiDocument doc) return; } - HostDocument = doc; + _hostDocument = doc; _schemaLoop.Clear(); _pathItemLoop.Clear(); @@ -902,9 +902,9 @@ internal JsonSchema Walk(JsonSchema schema, bool isComponent = false) Walk(key, () => newSchema = Walk(item.Value)); props.Add(key, newSchema); schema = builder.Properties(props); - if (HostDocument != null) + if (_hostDocument != null) { - schema.BaseUri = HostDocument.BaseUri; + schema.BaseUri = _hostDocument.BaseUri; } } });