@@ -485,9 +485,59 @@ function validate(n: ASTNode | undefined, schema: JSONSchema, validationResult:
485485 const testAlternatives = ( alternatives : JSONSchemaRef [ ] , maxOneMatch : boolean ) => {
486486 const matches = [ ] ;
487487
488+ // Apply discriminator optimization if available
489+ const discriminator = schema . discriminator ;
490+ let alternativesToTest = alternatives ;
491+
492+ if ( discriminator ) {
493+ // Extract discriminator value from node
494+ let discriminatorValue : string | undefined ;
495+ if ( node . type === 'object' && discriminator . propertyName ) {
496+ const prop = node . properties . find ( p => p . keyNode . value === discriminator . propertyName ) ;
497+ if ( prop ?. valueNode ?. type === 'string' ) {
498+ discriminatorValue = prop . valueNode . value ;
499+ }
500+ } else if ( node . type === 'array' && discriminator . propertyIndex !== undefined ) {
501+ const item = node . items [ discriminator . propertyIndex ] ;
502+ if ( item ?. type === 'string' ) {
503+ discriminatorValue = item . value ;
504+ }
505+ }
506+
507+ if ( discriminatorValue !== undefined ) {
508+ // Use explicit mapping if available
509+ if ( discriminator . mapping ) {
510+ const index = discriminator . mapping [ discriminatorValue ] ;
511+ if ( index !== undefined && index >= 0 && index < alternatives . length ) {
512+ alternativesToTest = [ alternatives [ index ] ] ;
513+ }
514+ } else {
515+ // Auto-detect matching schemas
516+ const matchingIndices = [ ] ;
517+ for ( let i = 0 ; i < alternatives . length ; i ++ ) {
518+ const altSchema = asSchema ( alternatives [ i ] ) ;
519+ if ( discriminator . propertyName && altSchema . properties ?. [ discriminator . propertyName ] ) {
520+ if ( asSchema ( altSchema . properties [ discriminator . propertyName ] ) . const === discriminatorValue ) {
521+ matchingIndices . push ( i ) ;
522+ }
523+ } else if ( discriminator . propertyIndex !== undefined ) {
524+ const itemSchema = altSchema . prefixItems ?. [ discriminator . propertyIndex ]
525+ ?? ( Array . isArray ( altSchema . items ) ? altSchema . items [ discriminator . propertyIndex ] : undefined ) ;
526+ if ( itemSchema && asSchema ( itemSchema ) . const === discriminatorValue ) {
527+ matchingIndices . push ( i ) ;
528+ }
529+ }
530+ }
531+ if ( matchingIndices . length > 0 ) {
532+ alternativesToTest = matchingIndices . map ( i => alternatives [ i ] ) ;
533+ }
534+ }
535+ }
536+ }
537+
488538 // remember the best match that is used for error messages
489539 let bestMatch : { schema : JSONSchema ; validationResult : ValidationResult ; matchingSchemas : ISchemaCollector ; } | undefined = undefined ;
490- for ( const subSchemaRef of alternatives ) {
540+ for ( const subSchemaRef of alternativesToTest ) {
491541 const subSchema = asSchema ( subSchemaRef ) ;
492542 const subValidationResult = new ValidationResult ( ) ;
493543 const subMatchingSchemas = matchingSchemas . newSub ( ) ;
0 commit comments