123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- package valid
- import (
- "context"
- "errors"
- "reflect"
- "strconv"
- )
- // Each returns a validation rule that loops through an iterable (map, slice or array)
- // and validates each value inside with the provided rules.
- // An empty iterable is considered valid. Use the Required rule to make sure the iterable is not empty.
- func Each(rules ...Rule) EachRule {
- return EachRule{
- rules: rules,
- }
- }
- // EachRule is a validation rule that validates elements in a map/slice/array using the specified list of rules.
- type EachRule struct {
- rules []Rule
- }
- // Validate loops through the given iterable and calls the Ozzo Validate() method for each value.
- func (r EachRule) Validate(value interface{}) error {
- return r.ValidateWithContext(nil, value)
- }
- // ValidateWithContext loops through the given iterable and calls the Ozzo ValidateWithContext() method for each value.
- func (r EachRule) ValidateWithContext(ctx context.Context, value interface{}) error {
- errs := Errors{}
- v := reflect.ValueOf(value)
- switch v.Kind() {
- case reflect.Map:
- for _, k := range v.MapKeys() {
- val := r.getInterface(v.MapIndex(k))
- var err error
- if ctx == nil {
- err = Validate(val, r.rules...)
- } else {
- err = ValidateWithContext(ctx, val, r.rules...)
- }
- if err != nil {
- errs[r.getString(k)] = err
- }
- }
- case reflect.Slice, reflect.Array:
- for i := 0; i < v.Len(); i++ {
- val := r.getInterface(v.Index(i))
- var err error
- if ctx == nil {
- err = Validate(val, r.rules...)
- } else {
- err = ValidateWithContext(ctx, val, r.rules...)
- }
- if err != nil {
- errs[strconv.Itoa(i)] = err
- }
- }
- default:
- return errors.New("must be an iterable (map, slice or array)")
- }
- if len(errs) > 0 {
- return errs
- }
- return nil
- }
- func (r EachRule) getInterface(value reflect.Value) interface{} {
- switch value.Kind() {
- case reflect.Ptr, reflect.Interface:
- if value.IsNil() {
- return nil
- }
- return value.Elem().Interface()
- default:
- return value.Interface()
- }
- }
- func (r EachRule) getString(value reflect.Value) string {
- switch value.Kind() {
- case reflect.Ptr, reflect.Interface:
- if value.IsNil() {
- return ""
- }
- return value.Elem().String()
- default:
- return value.String()
- }
- }
|