mirror of
https://github.com/Fishwaldo/validator.git
synced 2025-03-15 11:41:32 +00:00
Feat: support validate struct without struct tag (#934)
This commit is contained in:
parent
d3e4be3e44
commit
d0d0c355aa
3 changed files with 127 additions and 2 deletions
92
_examples/struct-map-rules-validation/main.go
Normal file
92
_examples/struct-map-rules-validation/main.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type Data struct {
|
||||
Name string
|
||||
Email string
|
||||
Details *Details
|
||||
}
|
||||
|
||||
type Details struct {
|
||||
FamilyMembers *FamilyMembers
|
||||
Salary string
|
||||
}
|
||||
|
||||
type FamilyMembers struct {
|
||||
FatherName string
|
||||
MotherName string
|
||||
}
|
||||
|
||||
type Data2 struct {
|
||||
Name string
|
||||
Age uint32
|
||||
}
|
||||
|
||||
var validate = validator.New()
|
||||
|
||||
func main() {
|
||||
validateStruct()
|
||||
// output
|
||||
// Key: 'Data2.Name' Error:Field validation for 'Name' failed on the 'min' tag
|
||||
// Key: 'Data2.Age' Error:Field validation for 'Age' failed on the 'max' tag
|
||||
|
||||
validateStructNested()
|
||||
// output
|
||||
// Key: 'Data.Name' Error:Field validation for 'Name' failed on the 'max' tag
|
||||
// Key: 'Data.Details.FamilyMembers' Error:Field validation for 'FamilyMembers' failed on the 'required' tag
|
||||
}
|
||||
|
||||
func validateStruct() {
|
||||
data := Data2{
|
||||
Name: "leo",
|
||||
Age: 1000,
|
||||
}
|
||||
|
||||
rules := map[string]string{
|
||||
"Name": "min=4,max=6",
|
||||
"Age": "min=4,max=6",
|
||||
}
|
||||
|
||||
validate.RegisterStructValidationMapRules(rules, Data2{})
|
||||
|
||||
err := validate.Struct(data)
|
||||
fmt.Println(err)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func validateStructNested() {
|
||||
data := Data{
|
||||
Name: "11sdfddd111",
|
||||
Email: "zytel3301@mail.com",
|
||||
Details: &Details{
|
||||
Salary: "1000",
|
||||
},
|
||||
}
|
||||
|
||||
rules1 := map[string]string{
|
||||
"Name": "min=4,max=6",
|
||||
"Email": "required,email",
|
||||
"Details": "required",
|
||||
}
|
||||
|
||||
rules2 := map[string]string{
|
||||
"Salary": "number",
|
||||
"FamilyMembers": "required",
|
||||
}
|
||||
|
||||
rules3 := map[string]string{
|
||||
"FatherName": "required,min=4,max=32",
|
||||
"MotherName": "required,min=4,max=32",
|
||||
}
|
||||
|
||||
validate.RegisterStructValidationMapRules(rules1, Data{})
|
||||
validate.RegisterStructValidationMapRules(rules2, Details{})
|
||||
validate.RegisterStructValidationMapRules(rules3, FamilyMembers{})
|
||||
err := validate.Struct(data)
|
||||
|
||||
fmt.Println(err)
|
||||
}
|
9
cache.go
9
cache.go
|
@ -114,12 +114,13 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
|
|||
cs = &cStruct{name: sName, fields: make([]*cField, 0), fn: v.structLevelFuncs[typ]}
|
||||
|
||||
numFields := current.NumField()
|
||||
rules := v.rules[typ]
|
||||
|
||||
var ctag *cTag
|
||||
var fld reflect.StructField
|
||||
var tag string
|
||||
var customName string
|
||||
|
||||
|
||||
for i := 0; i < numFields; i++ {
|
||||
|
||||
fld = typ.Field(i)
|
||||
|
@ -128,7 +129,11 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
|
|||
continue
|
||||
}
|
||||
|
||||
tag = fld.Tag.Get(v.tagName)
|
||||
if rtag, ok := rules[fld.Name]; ok {
|
||||
tag = rtag
|
||||
} else {
|
||||
tag = fld.Tag.Get(v.tagName)
|
||||
}
|
||||
|
||||
if tag == skipValidationTag {
|
||||
continue
|
||||
|
|
|
@ -86,6 +86,7 @@ type Validate struct {
|
|||
aliases map[string]string
|
||||
validations map[string]internalValidationFuncWrapper
|
||||
transTagFunc map[ut.Translator]map[string]TranslationFunc // map[<locale>]map[<tag>]TranslationFunc
|
||||
rules map[reflect.Type]map[string]string
|
||||
tagCache *tagCache
|
||||
structCache *structCache
|
||||
}
|
||||
|
@ -283,6 +284,33 @@ func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...i
|
|||
}
|
||||
}
|
||||
|
||||
// RegisterStructValidationMapRules registers validate map rules
|
||||
//
|
||||
// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
|
||||
func (v *Validate) RegisterStructValidationMapRules(rules map[string]string, types ...interface{}) {
|
||||
if v.rules == nil {
|
||||
v.rules = make(map[reflect.Type]map[string]string)
|
||||
}
|
||||
|
||||
deepCopyRules := make(map[string]string)
|
||||
for i, rule := range rules {
|
||||
deepCopyRules[i] = rule
|
||||
}
|
||||
|
||||
for _, t := range types {
|
||||
typ := reflect.TypeOf(t)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
||||
if typ.Kind() != reflect.Struct {
|
||||
continue
|
||||
}
|
||||
v.rules[typ] = deepCopyRules
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
|
||||
//
|
||||
// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
|
||||
|
|
Loading…
Add table
Reference in a new issue