github.com/kaptinlin/jsonschema@v0.4.6/anyOf.go (about)

     1  package jsonschema
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  // EvaluateAnyOf checks if the data conforms to at least one of the schemas specified in the anyOf attribute.
     8  // According to the JSON Schema Draft 2020-12:
     9  //   - The "anyOf" keyword's value must be a non-empty array, where each item is either a valid JSON Schema or a boolean.
    10  //   - An instance validates successfully against this keyword if it validates successfully against at least one schema or is true for any boolean in this array.
    11  //
    12  // This function ensures that the data instance meets at least one of the specified constraints defined by the schemas or booleans in the anyOf array.
    13  // If the instance fails to conform to all conditions in the array, it returns a EvaluationError detailing the specific failures.
    14  //
    15  // Reference: https://json-schema.org/draft/2020-12/json-schema-core#name-anyof
    16  func evaluateAnyOf(schema *Schema, data interface{}, evaluatedProps map[string]bool, evaluatedItems map[int]bool, dynamicScope *DynamicScope) ([]*EvaluationResult, *EvaluationError) {
    17  	if len(schema.AnyOf) == 0 {
    18  		return nil, nil // No anyOf constraints to validate against.
    19  	}
    20  
    21  	var valid bool
    22  	results := []*EvaluationResult{}
    23  
    24  	for i, subSchema := range schema.AnyOf {
    25  		if subSchema != nil {
    26  			skipEval := false
    27  			if subSchema.Boolean != nil && *subSchema.Boolean {
    28  				// If the schema is `true`, skip updating evaluated properties and items.
    29  				skipEval = true
    30  			}
    31  			result, schemaEvaluatedProps, schemaEvaluatedItems := subSchema.evaluate(data, dynamicScope)
    32  
    33  			if result != nil {
    34  				results = append(results, result.SetEvaluationPath(fmt.Sprintf("/anyOf/%d", i)).
    35  					SetSchemaLocation(schema.GetSchemaLocation(fmt.Sprintf("/anyOf/%d", i))).
    36  					SetInstanceLocation(""),
    37  				)
    38  
    39  				if result.IsValid() {
    40  					valid = true
    41  					// Merge maps only if the evaluation is successful
    42  					if !skipEval {
    43  						mergeStringMaps(evaluatedProps, schemaEvaluatedProps)
    44  						mergeIntMaps(evaluatedItems, schemaEvaluatedItems)
    45  					}
    46  				}
    47  			}
    48  		}
    49  	}
    50  
    51  	if valid {
    52  		return results, nil // Return nil only if at least one schema succeeds
    53  	} else {
    54  		return results, NewEvaluationError("anyOf", "any_of_item_mismatch", "Value does not match anyOf schema")
    55  	}
    56  }