github.com/kaptinlin/jsonschema@v0.4.6/conditional.go (about) 1 package jsonschema 2 3 // EvaluateConditional evaluates the data against conditional subschemas defined by 'if', 'then', and 'else'. 4 // According to the JSON Schema Draft 2020-12: 5 // - The "if" keyword specifies a subschema to conditionally validate data. 6 // - If data validates against the "if" subschema, "then" subschema must also validate the data if "then" is present. 7 // - If data does not validate against the "if" subschema, "else" subschema must validate the data if "else" is present. 8 // - This function ensures data conformity based on the provided conditional subschemaschema. 9 // - The function ignores "then" and "else" if "if" is not present. 10 // 11 // This function serves as a central feature for conditional logic application in JSON Schema validation. 12 // 13 // Reference: https://json-schema.org/draft/2020-12/json-schema-core#name-if 14 func evaluateConditional(schema *Schema, instance interface{}, evaluatedProps map[string]bool, evaluatedItems map[int]bool, dynamicScope *DynamicScope) ([]*EvaluationResult, *EvaluationError) { 15 if schema.If == nil { 16 // If there's no 'if' condition defined, nothing to validate conditionally. 17 return nil, nil 18 } 19 20 // Evaluate the 'if' condition 21 ifResult, ifEvaluatedProps, ifEvaluatedItems := schema.If.evaluate(instance, dynamicScope) 22 23 results := []*EvaluationResult{} 24 25 if ifResult != nil { 26 //nolint:errcheck 27 ifResult.SetEvaluationPath("/if"). 28 SetSchemaLocation(schema.GetSchemaLocation("/if")). 29 SetInstanceLocation("") 30 31 results = append(results, ifResult) 32 33 if ifResult.IsValid() { 34 // Merge maps only if 'if' condition is successfully validated 35 mergeStringMaps(evaluatedProps, ifEvaluatedProps) 36 mergeIntMaps(evaluatedItems, ifEvaluatedItems) 37 38 if schema.Then != nil { 39 thenResult, thenEvaluatedProps, thenEvaluatedItems := schema.Then.evaluate(instance, dynamicScope) 40 41 if thenResult != nil { 42 //nolint:errcheck 43 thenResult.SetEvaluationPath("/then"). 44 SetSchemaLocation(schema.GetSchemaLocation("/then")). 45 SetInstanceLocation("") 46 47 results = append(results, thenResult) 48 49 if !thenResult.IsValid() { 50 return results, NewEvaluationError("then", "if_then_mismatch", 51 "Value meets the 'if' condition but does not match the 'then' schema") 52 } else { 53 // Merge maps only if 'then' condition is successfully validated 54 mergeStringMaps(evaluatedProps, thenEvaluatedProps) 55 mergeIntMaps(evaluatedItems, thenEvaluatedItems) 56 } 57 } 58 } 59 } else if schema.Else != nil { 60 elseResult, elseEvaluatedProps, elseEvaluatedItems := schema.Else.evaluate(instance, dynamicScope) 61 if elseResult != nil { 62 results = append(results, elseResult) 63 64 if !elseResult.IsValid() { 65 return results, NewEvaluationError("else", "if_else_mismatch", 66 "Value fails the 'if' condition and does not match the 'else' schema") 67 } else { 68 // Merge maps only if 'else' condition is successfully validated 69 mergeStringMaps(evaluatedProps, elseEvaluatedProps) 70 mergeIntMaps(evaluatedItems, elseEvaluatedItems) 71 } 72 } 73 } 74 } 75 76 return results, nil 77 }