44using Microsoft . OpenApi . Models ;
55using Microsoft . OpenApi . Properties ;
66using System . Collections . Generic ;
7- using System . Linq ;
8- using System . Runtime . CompilerServices ;
97
108namespace Microsoft . OpenApi . Validations . Rules
119{
@@ -91,17 +89,28 @@ public static class OpenApiSchemaRules
9189 /// between other schemas which may satisfy the payload description.</param>
9290 public static bool ValidateChildSchemaAgainstDiscriminator ( OpenApiSchema schema , string discriminatorName )
9391 {
94- if ( discriminatorName == null )
92+ if ( ! schema . Required ? . Contains ( discriminatorName ) ?? false )
9593 {
96- return false ;
94+ // recursively check nested schema.OneOf, schema.AnyOf or schema.AllOf and their required fields for the discriminator
95+ if ( schema . OneOf . Count != 0 )
96+ {
97+ return TraverseSchemaElements ( discriminatorName , schema . OneOf ) ;
98+ }
99+ if ( schema . AnyOf . Count != 0 )
100+ {
101+ return TraverseSchemaElements ( discriminatorName , schema . AnyOf ) ;
102+ }
103+ if ( schema . AllOf . Count != 0 )
104+ {
105+ return TraverseSchemaElements ( discriminatorName , schema . AllOf ) ;
106+ }
97107 }
98-
99- if ( schema . Required ? . Contains ( discriminatorName ) == true )
108+ else
100109 {
101110 return true ;
102111 }
103112
104- return TraverseSchemaElementsIterative ( discriminatorName , GetSchemaCombinators ( schema ) ) ;
113+ return false ;
105114 }
106115
107116 /// <summary>
@@ -112,88 +121,21 @@ public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema,
112121 /// <param name="childSchema">The child schema.</param>
113122 /// <returns></returns>
114123 public static bool TraverseSchemaElements ( string discriminatorName , IList < OpenApiSchema > childSchema )
115- => TraverseSchemaElementsIterative ( discriminatorName , childSchema ) ;
116-
117- private static bool TraverseSchemaElementsIterative (
118- string discriminatorName ,
119- IEnumerable < OpenApiSchema > childSchemas )
120124 {
121- if ( childSchemas == null )
122- {
123- return false ;
124- }
125-
126- var schemasToVisit = new Queue < OpenApiSchema > ( ) ;
127- var visitedSchemas = new HashSet < OpenApiSchema > ( SchemaReferenceEqualityComparer . Instance ) ;
128-
129- EnqueueSchemas ( schemasToVisit , childSchemas ) ;
130-
131- while ( schemasToVisit . Count > 0 )
125+ foreach ( var childItem in childSchema )
132126 {
133- var childItem = schemasToVisit . Dequeue ( ) ;
134- if ( ! visitedSchemas . Add ( childItem ) )
127+ if ( ( ! childItem . Properties ? . ContainsKey ( discriminatorName ) ?? false ) &&
128+ ( ! childItem . Required ? . Contains ( discriminatorName ) ?? false ) )
135129 {
136- continue ;
130+ return ValidateChildSchemaAgainstDiscriminator ( childItem , discriminatorName ) ;
137131 }
138-
139- if ( childItem . Properties ? . ContainsKey ( discriminatorName ) == true ||
140- childItem . Required ? . Contains ( discriminatorName ) == true )
132+ else
141133 {
142134 return true ;
143135 }
144-
145- EnqueueSchemas ( schemasToVisit , GetSchemaCombinators ( childItem ) ) ;
146136 }
147137
148138 return false ;
149139 }
150-
151- private static IEnumerable < OpenApiSchema > GetSchemaCombinators ( OpenApiSchema schema )
152- {
153- if ( schema . OneOf != null )
154- {
155- foreach ( var childSchema in schema . OneOf )
156- {
157- yield return childSchema ;
158- }
159- }
160-
161- if ( schema . AnyOf != null )
162- {
163- foreach ( var childSchema in schema . AnyOf )
164- {
165- yield return childSchema ;
166- }
167- }
168-
169- if ( schema . AllOf != null )
170- {
171- foreach ( var childSchema in schema . AllOf )
172- {
173- yield return childSchema ;
174- }
175- }
176- }
177-
178- private static void EnqueueSchemas (
179- Queue < OpenApiSchema > schemasToVisit ,
180- IEnumerable < OpenApiSchema > childSchemas )
181- {
182- foreach ( var childSchema in childSchemas . Where ( childSchema => childSchema != null ) )
183- {
184- schemasToVisit . Enqueue ( childSchema ) ;
185- }
186- }
187-
188- private sealed class SchemaReferenceEqualityComparer : IEqualityComparer < OpenApiSchema >
189- {
190- internal static SchemaReferenceEqualityComparer Instance { get ; } = new ( ) ;
191-
192- public bool Equals ( OpenApiSchema x , OpenApiSchema y )
193- => ReferenceEquals ( x , y ) ;
194-
195- public int GetHashCode ( OpenApiSchema obj )
196- => RuntimeHelpers . GetHashCode ( obj ) ;
197- }
198140 }
199141}
0 commit comments