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 }