support custom message

pull/787/head
qm012 3 years ago
parent 76b917f432
commit 0b0f695dc5
  1. 1
      .gitignore
  2. 11
      cache.go
  3. 4
      errors.go
  4. 6
      validator.go
  5. 26
      validator_instance.go

1
.gitignore vendored

@ -26,5 +26,6 @@ _testmain.go
*.test
*.out
*.txt
.idea
cover.html
README.html

@ -79,6 +79,7 @@ type cField struct {
name string
altName string
namesEqual bool
tagValues map[string]string // custom multiple tag information tagname:tagvalue
cTags *cTag
}
@ -154,11 +155,21 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
ctag = new(cTag)
}
// handle custom tag map
length := len(v.customTags)
tagValues := make(map[string]string, length)
for i := 0; i < length; i++ {
ctname := v.customTags[i]
tagValues[ctname] = strings.TrimSpace(fld.Tag.Get(ctname))
}
cs.fields = append(cs.fields, &cField{
idx: i,
name: fld.Name,
altName: customName,
cTags: ctag,
tagValues: tagValues,
namesEqual: fld.Name == customName,
})
}

@ -177,6 +177,7 @@ type fieldError struct {
structfieldLen uint8
value interface{}
param string
cem string // custom error message
kind reflect.Kind
typ reflect.Type
}
@ -251,6 +252,9 @@ func (fe *fieldError) Type() reflect.Type {
// Error returns the fieldError's error message
func (fe *fieldError) Error() string {
if len(fe.cem) != 0 {
return fe.cem
}
return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
}

@ -128,6 +128,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
fieldLen: uint8(len(cf.altName)),
structfieldLen: uint8(len(cf.name)),
param: ct.param,
cem: cf.tagValues[defaultErrTagName],
kind: kind,
},
)
@ -152,6 +153,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
cem: cf.tagValues[defaultErrTagName],
kind: kind,
typ: current.Type(),
},
@ -197,6 +199,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
cem: cf.tagValues[defaultErrTagName],
kind: kind,
typ: typ,
},
@ -402,6 +405,7 @@ OUTER:
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
cem: cf.tagValues[defaultErrTagName],
kind: kind,
typ: typ,
},
@ -422,6 +426,7 @@ OUTER:
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
cem: cf.tagValues[defaultErrTagName],
kind: kind,
typ: typ,
},
@ -463,6 +468,7 @@ OUTER:
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
cem: cf.tagValues[defaultErrTagName],
kind: kind,
typ: typ,
},

@ -50,9 +50,22 @@ var (
timeDurationType = reflect.TypeOf(time.Duration(0))
timeType = reflect.TypeOf(time.Time{})
defaultCField = &cField{namesEqual: true}
defaultCField = &cField{namesEqual: true}
defaultErrTagName = "message"
)
// StringSlice is custom tag slice data
type StringSlice []string
func (s StringSlice) Position(name string) int {
for i := 0; i < len(s); i++ {
if s[i] == name {
return i
}
}
return -1
}
// FilterFunc is the type used to filter fields using
// StructFiltered(...) function.
// returning true results in the field being filtered/skiped from
@ -75,6 +88,7 @@ type internalValidationFuncWrapper struct {
// Validate contains the validator settings and cache
type Validate struct {
tagName string
customTags StringSlice
pool *sync.Pool
hasCustomFuncs bool
hasTagNameFunc bool
@ -99,6 +113,7 @@ func New() *Validate {
v := &Validate{
tagName: defaultTagName,
customTags: StringSlice{defaultErrTagName},
aliases: make(map[string]string, len(bakedInAliases)),
validations: make(map[string]internalValidationFuncWrapper, len(bakedInValidators)),
tagCache: tc,
@ -143,6 +158,15 @@ func (v *Validate) SetTagName(name string) {
v.tagName = name
}
// SetErrTagName allows for changing of the default tag name of 'message'
func (v *Validate) SetErrTagName(name string) {
index := v.customTags.Position(defaultErrTagName)
if index != -1 {
v.customTags[index] = name
}
defaultErrTagName = name
}
// ValidateMapCtx validates a map using a map of validation rules and allows passing of contextual
// validation validation information via context.Context.
func (v Validate) ValidateMapCtx(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {

Loading…
Cancel
Save