I'd like to validate the following structure :
type CarModel struct { gorm.Model OwnerID int `json:"ownerid" validate:"nonzero"` Type string `json:"type" validate:"regexp=(?)(A|B)"` A string `json:"url" validate:"isurl"` B string `json:"ip" validate:"isip"` }
I would like to validate A and B depending on Type, if type = A then A must exist and must be a URL BUT B must not exist if type = B then A must not exist and B must be an IP
is this possible with validator ?
I did try custom validation but I cannot find a way to see type value :
func checkB(v interface{}, param string) error {
theB := reflect.ValueOf(v)
if theB.Kind() != reflect.String {
return validator.ErrUnsupported
}
//check if B is an IP
ipcool := net.ParseIP(theB.String())
if ipcool == nil {
return errors.New("B : ip incorrecte " + theB.String())
}
return nil
}
Upon the answer of Alex Nichol, I would like first to thank you for your help.
If I understood correctly, I would have to iterate through all the "validate" fields, to keep a trace of the value of TYPE, A and B and then to check them depending on TYPE ...
I did this :
func checkMonitor(v interface{}) error {
var mytype string
var myA string
var myB string
val := reflect.ValueOf(v)
// Iterate through fields
for i := 0; i < val.NumField(); i++ {
// Lookup the validate tag
field := val.Type().Field(i)
tags := field.Tag
_, ok := tags.Lookup("validate")
if !ok {
// No validate tag.
continue
}
// Get the value of the field.
fieldValue := val.Field(i)
switch field.Name {
case "Type":
mytype = fieldValue.Interface()
case "A":
myA = fieldValue.Interface()
case "B":
myB = fieldValue.Interface()
}
// Validation logic here.
//fmt.Println("field", field.Name, "has validate tag", validate, "and value", fieldValue.Interface())
}
if mytype == "A" {
if myA == "" {
return errors.New("A vide et type A")
}
ipcool := net.ParseIP(myA)
if ipcool == nil {
return errors.New("A incorrecte " + myA)
}
} else if mytype == "HTML" {
if myB == "" {
return errors.New("B vide et type B")
}
_, urlpascool := url.ParseRequestURI(myB)
if urlpascool != nil {
return errors.New("B incorrecte " + myB)
}
}
return nil
}
but got an error on the mytype, myA and myB in the switch case :
cannot use fieldValue.Interface() (type interface {}) as type string in assignment: need type assertion
EDIT : just needed to use my brain :
switch field.Name {
case "Type":
mytype = fieldValue.String()
case "A":
myA = fieldValue.String()
case "B":
myB = fieldValue.Interface()
}