2017-02-22 9 views
0

Iは、以下の構造を検証したい:種類= A場合Golangバリデータ多門依存

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を検証したい うとURLでなければなりませんBは存在してはいけません タイプが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 
} 

、私はあなたの助けに感謝する最初たいと思います。

私が正しく理解している場合、私はTYPEの値のトレースを保つために、すべての「検証」フィールドを反復処理しなければならないが、AとB、その後、種類に応じて、それらをチェックする...

私はこのでした

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()割り当てを入力文字列として(型インターフェースを{})を使用することができません。タイプアサーションが必要

EDIT: ちょうど私の脳を使用するために必要な:

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

答えて

1

あなたはおそらく、構造体のフィールドを反復するためにリフレクションを使用し、各フィールドのvalidateタグを取得し、フィールドをチェックしたいです。つまり、構造レベルで検証を行う必要があります。そうでなければ、myInstance.OwnerIDのようなものを関数に渡すと、それに関連付けられたタグが失われます。

このコードは、構造体のフィールドをループし、それぞれのvalidateタグ取得:

checkStruct(CarModel{ 
    OwnerID: 2, 
    Type: "B", 
    A:  "http://google.com", 
    B:  "192.168.1.1", 
}) 

、それが印刷う:例えば

func checkStruct(v interface{}) error { 
    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 
     validate, ok := tags.Lookup("validate") 
     if !ok { 
      // No validate tag. 
      continue 
     } 

     // Get the value of the field. 
     fieldValue := val.Field(i) 

     // Validation logic here. 
     fmt.Println("field", field.Name, "has validate tag", validate, "and value", 
      fieldValue.Interface()) 
    } 
    return nil 
} 

を、我々はCarModel以下、それを渡すことができ以下をお読みください:

field OwnerID has validate tag nonzero and value 2 
field Type has validate tag regexp=(?)(A|B) and value B 
field A has validate tag isurl and value http://google.com 
field B has validate tag isip and value 192.168.1.1 
0

あなたの検証のようですルールは非常に複雑ですが、validatingを試すことができます。

次のようにあなたの検証ルールを実装することができ、我々はすでに2つのカスタマイズされたバリデータIsURLIsIPがあるとします。

import (
    "regexp" 

    v "github.com/RussellLuo/validating" 
) 

// Customized validators 
var (
    MatchRegexp = func(pattern string) v.Validator { 
     return v.FromFunc(func(field v.Field) v.Errors { 
      switch t := field.ValuePtr.(type) { 
      case *string: 
       if matched, _ := regexp.MatchString(pattern, *t); !matched { 
        return v.NewErrors(field.Name, v.ErrInvalid, "does not match") 
       } 
       return nil 
      default: 
       return v.NewErrors(field.Name, v.ErrUnsupported, "is unsupported") 
      } 
     }) 
    } 
    // IsURL and IsIP are omitted 
) 

type CarModel struct { 
    gorm.Model 
    OwnerID int `json:"ownerid"` 
    Type  string `json:"type"` 
    A   string `json:"url"` 
    B   string `json:"ip"` 
} 

func main() { 
    car := CarModel{} 
    errs := v.Validate(v.Schema{ 
     v.F("ownerid", &car.OwnerID): v.Nonzero(), 
     v.F("type", &car.Type):  MatchRegexp("(A|B)"), 
     v.F("a", &car.A): v.Lazy(func() v.Validator { 
      if car.Type == "A" { 
       return v.All(v.Nonzero(), IsURL()) 
      } 
      return v.Not(v.Nonzero()) 
     }), 
     v.F("b", &car.B): v.Lazy(func() v.Validator { 
      if car.Type == "B" { 
       return v.All(v.Nonzero(), IsIP()) 
      } 
      return v.Not(v.Nonzero()) 
     }), 
    }) 
} 
関連する問題