diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs
index 1639e6248..a8ed2e93c 100644
--- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs
+++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
-using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Properties;
using System.Collections.Generic;
@@ -11,7 +10,6 @@ namespace Microsoft.OpenApi.Validations.Rules
///
/// The validation rules for .
///
-
[OpenApiRule]
public static class OpenApiSchemaRules
{
@@ -70,15 +68,74 @@ public static class OpenApiSchemaRules
if (schema.Reference != null && schema.Discriminator != null)
{
- if (!schema.Required.Contains(schema.Discriminator?.PropertyName))
+ var discriminatorName = schema.Discriminator?.PropertyName;
+
+ if (!ValidateChildSchemaAgainstDiscriminator(schema, discriminatorName))
{
context.CreateError(nameof(ValidateSchemaDiscriminator),
- string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator,
- schema.Reference.Id, schema.Discriminator.PropertyName));
+ string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator,
+ schema.Reference.Id, discriminatorName));
}
}
context.Exit();
});
+
+ ///
+ /// Validates the property name in the discriminator against the ones present in the children schema
+ ///
+ /// The parent schema.
+ /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate
+ /// between other schemas which may satisfy the payload description.
+ public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema, string discriminatorName)
+ {
+ if (!schema.Required?.Contains(discriminatorName) ?? false)
+ {
+ // recursively check nested schema.OneOf, schema.AnyOf or schema.AllOf and their required fields for the discriminator
+ if (schema.OneOf.Count != 0)
+ {
+ return TraverseSchemaElements(discriminatorName, schema.OneOf);
+ }
+ if (schema.AnyOf.Count != 0)
+ {
+ return TraverseSchemaElements(discriminatorName, schema.AnyOf);
+ }
+ if (schema.AllOf.Count != 0)
+ {
+ return TraverseSchemaElements(discriminatorName, schema.AllOf);
+ }
+ }
+ else
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Traverses the schema elements and checks whether the schema contains the discriminator.
+ ///
+ /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate
+ /// between other schemas which may satisfy the payload description.
+ /// The child schema.
+ ///
+ public static bool TraverseSchemaElements(string discriminatorName, IList childSchema)
+ {
+ foreach (var childItem in childSchema)
+ {
+ if ((!childItem.Properties?.ContainsKey(discriminatorName) ?? false) &&
+ (!childItem.Required?.Contains(discriminatorName) ?? false))
+ {
+ return ValidateChildSchemaAgainstDiscriminator(childItem, discriminatorName);
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
}
diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
index e9d78acb2..c8930e9fb 100755
--- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
+++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
@@ -1283,6 +1283,8 @@ namespace Microsoft.OpenApi.Validations.Rules
{
public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; }
public static Microsoft.OpenApi.Validations.ValidationRule ValidateSchemaDiscriminator { get; }
+ public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList childSchema) { }
+ public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.Models.OpenApiSchema schema, string discriminatorName) { }
}
[Microsoft.OpenApi.Validations.Rules.OpenApiRule]
public static class OpenApiServerRules
diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs
index d239e15a1..04acf7737 100644
--- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs
+++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs
@@ -268,5 +268,60 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD
"schema1", "property1"))
});
}
+
+ [Fact]
+ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminator()
+ {
+ // Arrange
+ var components = new OpenApiComponents
+ {
+ Schemas =
+ {
+ {
+ "Person",
+ new OpenApiSchema
+ {
+ Type = "array",
+ Discriminator = new OpenApiDiscriminator
+ {
+ PropertyName = "type"
+ },
+ OneOf = new List
+ {
+ new OpenApiSchema
+ {
+ Properties =
+ {
+ {
+ "type",
+ new OpenApiSchema
+ {
+ Type = "array"
+ }
+ }
+ },
+ Reference = new OpenApiReference
+ {
+ Type = ReferenceType.Schema,
+ Id = "Person"
+ }
+ }
+ },
+ Reference = new OpenApiReference { Id = "Person" }
+ }
+ }
+ }
+ };
+
+ // Act
+ var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet());
+ var walker = new OpenApiWalker(validator);
+ walker.Walk(components);
+
+ var errors = validator.Errors;
+
+ //Assert
+ errors.Should().BeEmpty();
+ }
}
}