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

     1  package jsonschema
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // EvaluateItems checks if the data's array items conform to the subschema or boolean condition specified in the 'items' attribute of the schema.
    10  // According to the JSON Schema Draft 2020-12:
    11  //   - The value of "items" MUST be either a valid JSON Schema or a boolean.
    12  //   - If "items" is a Schema, each element of the instance array must conform to this subschema.
    13  //   - If "items" is boolean and is true, any array elements are valid.
    14  //   - If "items" is boolean and is false, no array elements are valid unless the array is empty.
    15  //
    16  // This method ensures that array elements conform to the constraints defined in the items attribute.
    17  // If any array element does not conform, it returns a EvaluationError detailing the issue.
    18  //
    19  // Reference: https://json-schema.org/draft/2020-12/json-schema-core#name-items
    20  func evaluateItems(schema *Schema, array []interface{}, _ map[string]bool, evaluatedItems map[int]bool, dynamicScope *DynamicScope) ([]*EvaluationResult, *EvaluationError) {
    21  	if schema.Items == nil {
    22  		return nil, nil // // No 'items' constraints to validate against
    23  	}
    24  
    25  	invalid_indexs := []string{}
    26  	results := []*EvaluationResult{}
    27  
    28  	// Number of prefix items to skip before regular item validation
    29  	startIndex := len(schema.PrefixItems)
    30  
    31  	// Check if the general 'items' schema is available and proceed with validation if it's not explicitly false
    32  	if schema.Items != nil {
    33  		// Ensure that we only access indices within the range of existing array elements
    34  		for i := startIndex; i < len(array); i++ {
    35  			item := array[i]
    36  			result, _, _ := schema.Items.evaluate(item, dynamicScope)
    37  			if result != nil {
    38  				//nolint:errcheck
    39  				result.SetEvaluationPath(fmt.Sprintf("/items/%d", i)).
    40  					SetSchemaLocation(schema.GetSchemaLocation(fmt.Sprintf("/items/%d", i))).
    41  					SetInstanceLocation(fmt.Sprintf("/%d", i))
    42  
    43  				if result.IsValid() {
    44  					evaluatedItems[i] = true // Mark the item as evaluated if it passes schema validation.
    45  				} else {
    46  					results = append(results, result)
    47  					invalid_indexs = append(invalid_indexs, strconv.Itoa(i))
    48  				}
    49  			}
    50  		}
    51  	}
    52  
    53  	if len(invalid_indexs) == 1 {
    54  		return results, NewEvaluationError("items", "item_mismatch", "Item at index {index} does not match the schema", map[string]interface{}{
    55  			"index": invalid_indexs[0],
    56  		})
    57  	} else if len(invalid_indexs) > 1 {
    58  		return results, NewEvaluationError("items", "items_mismatch", "Items at index {indexs} do not match the schema", map[string]interface{}{
    59  			"indexs": strings.Join(invalid_indexs, ", "),
    60  		})
    61  	}
    62  	return results, nil
    63  }