Golang验证器多字段依赖

时间:2017-02-22 11:50:17

标签: validation go struct

我想验证以下结构:

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"`
}

我想根据类型验证A和B, 如果type = A则A必须存在且必须是URL但B不能存在 如果type = B则A不能存在,B必须是IP

这可以通过验证器吗?

我确实尝试过自定义验证,但我找不到查看类型值的方法:

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
}

根据Alex Nichol的回答,我想首先感谢你的帮助。

如果我理解正确,我将不得不遍历所有“验证”字段,以跟踪TYPE,A和B的值,然后根据TYPE检查它们......

我这样做了:

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
}

但在切换案例中mytype,myA和myB出错:

不能在赋值时使用fieldValue.Interface()(type interface {})作为类型字符串:need type assertion

编辑: 只需要使用我的大脑:

switch field.Name {
case "Type":
   mytype = fieldValue.String()
case "A":
   myA = fieldValue.String()
case "B":
   myB = fieldValue.Interface()
}

1 个答案:

答案 0 :(得分:0)

似乎您的验证规则非常复杂,但您可以尝试validating

假设我们已经有两个自定义验证器<div class="skills"> <h1>Skills</h1> <div class="skill-box"> <p>HTML</p> <div class="container-skill"> <div class="skill html">90%</div> </div> <p>CSS</p> <div class="container-skill"> <div class="skill css">80%</div> </div> <p>JavaScript</p> <div class="container-skill"> <div class="skill js">65%</div> </div> <p>PHP</p> <div class="container-skill"> <div class="skill php">60%</div> </div> </div> </div>IsURL,那么您的验证规则可以按如下方式实施:

IsIP