gopkg.in/simversity/gottp.v3@v3.0.0-20160401065405-576cf030ca0e/utils/validate.go (about)

     1  package utils
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"strings"
     7  )
     8  
     9  func Validate(obj interface{}) *[]error {
    10  	faults := []error{}
    11  	ValidateStruct(&faults, obj)
    12  	return &faults
    13  }
    14  
    15  func ValidateStruct(faults *[]error, obj interface{}) {
    16  	typ := reflect.TypeOf(obj)
    17  	val := reflect.ValueOf(obj)
    18  
    19  	if typ.Kind() == reflect.Ptr {
    20  		typ = typ.Elem()
    21  		val = val.Elem()
    22  	}
    23  
    24  	for i := 0; i < typ.NumField(); i++ {
    25  		field := typ.Field(i)
    26  
    27  		// Skip ignored and unexported fields in the struct
    28  		if !val.Field(i).CanInterface() {
    29  			continue
    30  		}
    31  
    32  		fieldValue := val.Field(i).Interface()
    33  		zero := reflect.Zero(field.Type).Interface()
    34  
    35  		// Validate nested and embedded structs (if pointer, only do so if not nil)
    36  		if field.Type.Kind() == reflect.Struct ||
    37  			(field.Type.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, fieldValue) &&
    38  				field.Type.Elem().Kind() == reflect.Struct) {
    39  			ValidateStruct(faults, fieldValue)
    40  		}
    41  
    42  		if strings.Index(field.Tag.Get("required"), "true") > -1 {
    43  			if reflect.DeepEqual(zero, fieldValue) {
    44  
    45  				name := field.Name
    46  				if j := field.Tag.Get("json"); j != "" {
    47  					name = j
    48  				}
    49  
    50  				*faults = append(*faults, errors.New(name+" is a required field"))
    51  			}
    52  		}
    53  	}
    54  }