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

     1  package jsonschema
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // EvaluatePrefixItems checks if each element in an array instance matches the schema specified at the same index in the 'prefixItems' array.
    10  // According to the JSON Schema Draft 2020-12:
    11  //   - The value of "prefixItems" MUST be a non-empty array of valid JSON Schemas.
    12  //   - Validation succeeds if each element of the instance validates against the schema at the same position, if any.
    13  //   - This keyword does not constrain the length of the array; it validates only the prefix of the array up to the length of 'prefixItems'.
    14  //   - Produces an annotation value of the largest index validated if all items up to that index are valid. The value may be true if all items are valid.
    15  //   - Omitting this keyword implies an empty array behavior, meaning no validation is enforced on the array items.
    16  //
    17  // If validation fails, it returns a EvaluationError detailing the index and discrepancy.
    18  func evaluatePrefixItems(schema *Schema, array []interface{}, _ map[string]bool, evaluatedItems map[int]bool, dynamicScope *DynamicScope) ([]*EvaluationResult, *EvaluationError) {
    19  	if len(schema.PrefixItems) == 0 {
    20  		return nil, nil // If no prefixItems are defined, there is nothing to validate against.
    21  	}
    22  
    23  	invalid_indexs := []string{}
    24  	results := []*EvaluationResult{}
    25  
    26  	for i, itemSchema := range schema.PrefixItems {
    27  		if i >= len(array) {
    28  			break // Stop validation if there are more schemas than array items.
    29  		}
    30  
    31  		result, _, _ := itemSchema.evaluate(array[i], dynamicScope)
    32  		if result != nil {
    33  			results = append(results, result.SetEvaluationPath(fmt.Sprintf("/prefixItems/%d", i)).
    34  				SetSchemaLocation(schema.GetSchemaLocation(fmt.Sprintf("/prefixItems/%d", i))).
    35  				SetInstanceLocation(fmt.Sprintf("/%d", i)),
    36  			)
    37  
    38  			if result.IsValid() {
    39  				evaluatedItems[i] = true // Mark the item as evaluated if it passes schema validation.
    40  			} else {
    41  				invalid_indexs = append(invalid_indexs, strconv.Itoa(i))
    42  			}
    43  		}
    44  	}
    45  
    46  	if len(invalid_indexs) == 1 {
    47  		return results, NewEvaluationError("prefixItems", "prefix_item_mismatch", "Item at index {index} does not match the prefixItems schema", map[string]interface{}{
    48  			"index": invalid_indexs[0],
    49  		})
    50  	} else if len(invalid_indexs) > 1 {
    51  		return results, NewEvaluationError("prefixItems", "prefix_items_mismatch", "Items at index {indexs} do not match the prefixItems schemas", map[string]interface{}{
    52  			"indexs": strings.Join(invalid_indexs, ", "),
    53  		})
    54  	}
    55  
    56  	return results, nil
    57  }