51 | 51 |
TopStruct reflect.Value
|
52 | 52 |
CurrentStruct reflect.Value
|
53 | 53 |
errPrefix string
|
|
54 |
nsPrefix string
|
54 | 55 |
errs ValidationErrors
|
55 | 56 |
v *Validate
|
56 | 57 |
}
|
|
59 | 60 |
// Example: had a triple nested struct User, ContactInfo, Country and ran errs := validate.Struct(country)
|
60 | 61 |
// from within a User struct level validation would call this method like so:
|
61 | 62 |
// ReportValidationErrors("ContactInfo.", errs)
|
|
63 |
// NOTE: relativeKey can contain both the Field Relative and Custom name relative paths
|
|
64 |
// i.e. ReportValidationErrors("ContactInfo.|cInfo", errs) where cInfo represents say the JSON name of
|
|
65 |
// the relative path; this will be split into 2 variables in the next valiator version.
|
62 | 66 |
func (sl *StructLevel) ReportValidationErrors(relativeKey string, errs ValidationErrors) {
|
63 | 67 |
for _, e := range errs {
|
64 | |
sl.errs[sl.errPrefix+relativeKey+e.Field] = e
|
|
68 |
|
|
69 |
idx := strings.Index(relativeKey, "|")
|
|
70 |
var rel string
|
|
71 |
var cRel string
|
|
72 |
|
|
73 |
if idx != -1 {
|
|
74 |
rel = relativeKey[:idx]
|
|
75 |
cRel = relativeKey[idx+1:]
|
|
76 |
} else {
|
|
77 |
rel = relativeKey
|
|
78 |
}
|
|
79 |
|
|
80 |
key := sl.errPrefix + rel + e.Field
|
|
81 |
|
|
82 |
e.FieldNamespace = key
|
|
83 |
e.NameNamespace = sl.nsPrefix + cRel + e.Name
|
|
84 |
|
|
85 |
sl.errs[key] = e
|
65 | 86 |
}
|
66 | 87 |
}
|
67 | 88 |
|
|
72 | 93 |
|
73 | 94 |
field, kind := sl.v.ExtractType(field)
|
74 | 95 |
|
75 | |
if len(fieldName) == 0 {
|
|
96 |
if fieldName == blank {
|
76 | 97 |
panic(fieldNameRequired)
|
77 | 98 |
}
|
78 | 99 |
|
79 | |
if len(customName) == 0 {
|
|
100 |
if customName == blank {
|
80 | 101 |
customName = fieldName
|
81 | 102 |
}
|
82 | 103 |
|
83 | |
if len(tag) == 0 {
|
|
104 |
if tag == blank {
|
84 | 105 |
panic(tagRequired)
|
85 | 106 |
}
|
|
107 |
|
|
108 |
ns := sl.errPrefix + fieldName
|
86 | 109 |
|
87 | 110 |
switch kind {
|
88 | 111 |
case reflect.Invalid:
|
89 | |
sl.errs[sl.errPrefix+fieldName] = &FieldError{
|
90 | |
Name: customName,
|
91 | |
Field: fieldName,
|
92 | |
Tag: tag,
|
93 | |
ActualTag: tag,
|
94 | |
Param: blank,
|
95 | |
Kind: kind,
|
|
112 |
sl.errs[ns] = &FieldError{
|
|
113 |
FieldNamespace: ns,
|
|
114 |
NameNamespace: sl.nsPrefix + customName,
|
|
115 |
Name: customName,
|
|
116 |
Field: fieldName,
|
|
117 |
Tag: tag,
|
|
118 |
ActualTag: tag,
|
|
119 |
Param: blank,
|
|
120 |
Kind: kind,
|
96 | 121 |
}
|
97 | 122 |
default:
|
98 | |
sl.errs[sl.errPrefix+fieldName] = &FieldError{
|
99 | |
Name: customName,
|
100 | |
Field: fieldName,
|
101 | |
Tag: tag,
|
102 | |
ActualTag: tag,
|
103 | |
Param: blank,
|
104 | |
Value: field.Interface(),
|
105 | |
Kind: kind,
|
106 | |
Type: field.Type(),
|
|
123 |
sl.errs[ns] = &FieldError{
|
|
124 |
FieldNamespace: ns,
|
|
125 |
NameNamespace: sl.nsPrefix + customName,
|
|
126 |
Name: customName,
|
|
127 |
Field: fieldName,
|
|
128 |
Tag: tag,
|
|
129 |
ActualTag: tag,
|
|
130 |
Param: blank,
|
|
131 |
Value: field.Interface(),
|
|
132 |
Kind: kind,
|
|
133 |
Type: field.Type(),
|
107 | 134 |
}
|
108 | 135 |
}
|
109 | 136 |
}
|
|
177 | 204 |
// FieldError contains a single field's validation error along
|
178 | 205 |
// with other properties that may be needed for error message creation
|
179 | 206 |
type FieldError struct {
|
180 | |
Field string
|
181 | |
Name string
|
182 | |
Tag string
|
183 | |
ActualTag string
|
184 | |
Kind reflect.Kind
|
185 | |
Type reflect.Type
|
186 | |
Param string
|
187 | |
Value interface{}
|
|
207 |
FieldNamespace string
|
|
208 |
NameNamespace string
|
|
209 |
Field string
|
|
210 |
Name string
|
|
211 |
Tag string
|
|
212 |
ActualTag string
|
|
213 |
Kind reflect.Kind
|
|
214 |
Type reflect.Type
|
|
215 |
Param string
|
|
216 |
Value interface{}
|
188 | 217 |
}
|
189 | 218 |
|
190 | 219 |
// New creates a new Validate instance for use.
|
|
240 | 269 |
func (v *Validate) RegisterValidation(key string, fn Func) error {
|
241 | 270 |
v.initCheck()
|
242 | 271 |
|
243 | |
if len(key) == 0 {
|
|
272 |
if key == blank {
|
244 | 273 |
return errors.New("Function Key cannot be empty")
|
245 | 274 |
}
|
246 | 275 |
|
|
305 | 334 |
errs := v.errsPool.Get().(ValidationErrors)
|
306 | 335 |
fieldVal := reflect.ValueOf(field)
|
307 | 336 |
|
308 | |
v.traverseField(fieldVal, fieldVal, fieldVal, blank, errs, false, tag, blank, blank, false, false, nil, nil)
|
|
337 |
v.traverseField(fieldVal, fieldVal, fieldVal, blank, blank, errs, false, tag, blank, blank, false, false, nil, nil)
|
309 | 338 |
|
310 | 339 |
if len(errs) == 0 {
|
311 | 340 |
v.errsPool.Put(errs)
|
|
325 | 354 |
errs := v.errsPool.Get().(ValidationErrors)
|
326 | 355 |
topVal := reflect.ValueOf(val)
|
327 | 356 |
|
328 | |
v.traverseField(topVal, topVal, reflect.ValueOf(field), blank, errs, false, tag, blank, blank, false, false, nil, nil)
|
|
357 |
v.traverseField(topVal, topVal, reflect.ValueOf(field), blank, blank, errs, false, tag, blank, blank, false, false, nil, nil)
|
329 | 358 |
|
330 | 359 |
if len(errs) == 0 {
|
331 | 360 |
v.errsPool.Put(errs)
|
|
383 | 412 |
|
384 | 413 |
errs := v.errsPool.Get().(ValidationErrors)
|
385 | 414 |
|
386 | |
v.tranverseStruct(sv, sv, sv, blank, errs, true, len(m) != 0, false, m, false)
|
|
415 |
v.tranverseStruct(sv, sv, sv, blank, blank, errs, true, len(m) != 0, false, m, false)
|
387 | 416 |
|
388 | 417 |
if len(errs) == 0 {
|
389 | 418 |
v.errsPool.Put(errs)
|
|
405 | 434 |
m := map[string]*struct{}{}
|
406 | 435 |
|
407 | 436 |
for _, key := range fields {
|
408 | |
m[name+"."+key] = emptyStructPtr
|
|
437 |
m[name+namespaceSeparator+key] = emptyStructPtr
|
409 | 438 |
}
|
410 | 439 |
|
411 | 440 |
errs := v.errsPool.Get().(ValidationErrors)
|
412 | 441 |
|
413 | |
v.tranverseStruct(sv, sv, sv, blank, errs, true, len(m) != 0, true, m, false)
|
|
442 |
v.tranverseStruct(sv, sv, sv, blank, blank, errs, true, len(m) != 0, true, m, false)
|
414 | 443 |
|
415 | 444 |
if len(errs) == 0 {
|
416 | 445 |
v.errsPool.Put(errs)
|
|
429 | 458 |
errs := v.errsPool.Get().(ValidationErrors)
|
430 | 459 |
sv := reflect.ValueOf(current)
|
431 | 460 |
|
432 | |
v.tranverseStruct(sv, sv, sv, blank, errs, true, false, false, nil, false)
|
|
461 |
v.tranverseStruct(sv, sv, sv, blank, blank, errs, true, false, false, nil, false)
|
433 | 462 |
|
434 | 463 |
if len(errs) == 0 {
|
435 | 464 |
v.errsPool.Put(errs)
|
|
440 | 469 |
}
|
441 | 470 |
|
442 | 471 |
// tranverseStruct traverses a structs fields and then passes them to be validated by traverseField
|
443 | |
func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, useStructName bool, partial bool, exclude bool, includeExclude map[string]*struct{}, isStructOnly bool) {
|
|
472 |
func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, useStructName bool, partial bool, exclude bool, includeExclude map[string]*struct{}, isStructOnly bool) {
|
444 | 473 |
|
445 | 474 |
if current.Kind() == reflect.Ptr && !current.IsNil() {
|
446 | 475 |
current = current.Elem()
|
|
456 | 485 |
sName := typ.Name()
|
457 | 486 |
|
458 | 487 |
if useStructName {
|
459 | |
errPrefix += sName + "."
|
|
488 |
errPrefix += sName + namespaceSeparator
|
|
489 |
|
|
490 |
if v.fieldNameTag != blank {
|
|
491 |
nsPrefix += sName + namespaceSeparator
|
|
492 |
}
|
460 | 493 |
}
|
461 | 494 |
|
462 | 495 |
// structonly tag present don't tranverseFields
|
|
468 | 501 |
|
469 | 502 |
// is anonymous struct, cannot parse or cache as
|
470 | 503 |
// it has no name to index by
|
471 | |
if len(sName) == 0 {
|
|
504 |
if sName == blank {
|
472 | 505 |
|
473 | 506 |
var customName string
|
474 | 507 |
var ok bool
|
|
478 | 511 |
|
479 | 512 |
fld = typ.Field(i)
|
480 | 513 |
|
481 | |
if len(fld.PkgPath) != 0 {
|
|
514 |
if fld.PkgPath != blank {
|
482 | 515 |
continue
|
483 | 516 |
}
|
484 | 517 |
|
|
492 | 525 |
}
|
493 | 526 |
|
494 | 527 |
customName = fld.Name
|
495 | |
if v.fieldNameTag != "" {
|
|
528 |
|
|
529 |
if v.fieldNameTag != blank {
|
496 | 530 |
|
497 | 531 |
name := strings.SplitN(fld.Tag.Get(v.fieldNameTag), ",", 2)[0]
|
498 | 532 |
|
499 | 533 |
// dash check is for json "-" means don't output in json
|
500 | |
if name != "" && name != "-" {
|
|
534 |
if name != blank && name != dash {
|
501 | 535 |
customName = name
|
502 | 536 |
}
|
503 | 537 |
}
|
504 | 538 |
|
505 | |
v.traverseField(topStruct, currentStruct, current.Field(i), errPrefix, errs, true, fld.Tag.Get(v.tagName), fld.Name, customName, partial, exclude, includeExclude, nil)
|
|
539 |
v.traverseField(topStruct, currentStruct, current.Field(i), errPrefix, nsPrefix, errs, true, fld.Tag.Get(v.tagName), fld.Name, customName, partial, exclude, includeExclude, nil)
|
506 | 540 |
}
|
507 | 541 |
} else {
|
508 | 542 |
s, ok := v.structCache.Get(typ)
|
|
522 | 556 |
}
|
523 | 557 |
fld = typ.Field(i)
|
524 | 558 |
|
525 | |
v.traverseField(topStruct, currentStruct, current.Field(i), errPrefix, errs, true, f.CachedTag.tag, fld.Name, f.AltName, partial, exclude, includeExclude, f.CachedTag)
|
|
559 |
v.traverseField(topStruct, currentStruct, current.Field(i), errPrefix, nsPrefix, errs, true, f.CachedTag.tag, fld.Name, f.AltName, partial, exclude, includeExclude, f.CachedTag)
|
526 | 560 |
}
|
527 | 561 |
}
|
528 | 562 |
}
|
|
530 | 564 |
// check if any struct level validations, after all field validations already checked.
|
531 | 565 |
if v.hasStructLevelFuncs {
|
532 | 566 |
if fn, ok := v.structLevelFuncs[current.Type()]; ok {
|
533 | |
fn(v, &StructLevel{v: v, TopStruct: topStruct, CurrentStruct: current, errPrefix: errPrefix, errs: errs})
|
|
567 |
fn(v, &StructLevel{v: v, TopStruct: topStruct, CurrentStruct: current, errPrefix: errPrefix, nsPrefix: nsPrefix, errs: errs})
|
534 | 568 |
}
|
535 | 569 |
}
|
536 | 570 |
}
|
537 | 571 |
|
538 | 572 |
// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
|
539 | |
func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, isStructField bool, tag, name, customName string, partial bool, exclude bool, includeExclude map[string]*struct{}, cTag *cachedTag) {
|
|
573 |
func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, isStructField bool, tag, name, customName string, partial bool, exclude bool, includeExclude map[string]*struct{}, cTag *cachedTag) {
|
540 | 574 |
|
541 | 575 |
if tag == skipValidationTag {
|
542 | 576 |
return
|
|
560 | 594 |
return
|
561 | 595 |
}
|
562 | 596 |
|
563 | |
if len(tag) > 0 {
|
|
597 |
if tag != blank {
|
|
598 |
|
|
599 |
ns := errPrefix + name
|
564 | 600 |
|
565 | 601 |
if kind == reflect.Invalid {
|
566 | |
errs[errPrefix+name] = &FieldError{
|
567 | |
Name: customName,
|
568 | |
Field: name,
|
569 | |
Tag: cTag.tags[0].tag,
|
570 | |
ActualTag: cTag.tags[0].tagVals[0][0],
|
571 | |
Param: cTag.tags[0].tagVals[0][1],
|
572 | |
Kind: kind,
|
|
602 |
errs[ns] = &FieldError{
|
|
603 |
FieldNamespace: ns,
|
|
604 |
NameNamespace: nsPrefix + customName,
|
|
605 |
Name: customName,
|
|
606 |
Field: name,
|
|
607 |
Tag: cTag.tags[0].tag,
|
|
608 |
ActualTag: cTag.tags[0].tagVals[0][0],
|
|
609 |
Param: cTag.tags[0].tagVals[0][1],
|
|
610 |
Kind: kind,
|
573 | 611 |
}
|
574 | 612 |
return
|
575 | 613 |
}
|
576 | 614 |
|
577 | |
errs[errPrefix+name] = &FieldError{
|
578 | |
Name: customName,
|
579 | |
Field: name,
|
580 | |
Tag: cTag.tags[0].tag,
|
581 | |
ActualTag: cTag.tags[0].tagVals[0][0],
|
582 | |
Param: cTag.tags[0].tagVals[0][1],
|
583 | |
Value: current.Interface(),
|
584 | |
Kind: kind,
|
585 | |
Type: current.Type(),
|
|
615 |
errs[ns] = &FieldError{
|
|
616 |
FieldNamespace: ns,
|
|
617 |
NameNamespace: nsPrefix + customName,
|
|
618 |
Name: customName,
|
|
619 |
Field: name,
|
|
620 |
Tag: cTag.tags[0].tag,
|
|
621 |
ActualTag: cTag.tags[0].tagVals[0][0],
|
|
622 |
Param: cTag.tags[0].tagVals[0][1],
|
|
623 |
Value: current.Interface(),
|
|
624 |
Kind: kind,
|
|
625 |
Type: current.Type(),
|
586 | 626 |
}
|
587 | 627 |
|
588 | 628 |
return
|
|
602 | 642 |
return
|
603 | 643 |
}
|
604 | 644 |
|
605 | |
v.tranverseStruct(topStruct, current, current, errPrefix+name+".", errs, false, partial, exclude, includeExclude, cTag.isStructOnly)
|
|
645 |
v.tranverseStruct(topStruct, current, current, errPrefix+name+namespaceSeparator, nsPrefix+customName+namespaceSeparator, errs, false, partial, exclude, includeExclude, cTag.isStructOnly)
|
606 | 646 |
return
|
607 | 647 |
}
|
608 | 648 |
}
|
609 | 649 |
|
610 | |
if len(tag) == 0 {
|
|
650 |
if tag == blank {
|
611 | 651 |
return
|
612 | 652 |
}
|
613 | 653 |
|
|
636 | 676 |
continue
|
637 | 677 |
}
|
638 | 678 |
|
639 | |
if v.validateField(topStruct, currentStruct, current, typ, kind, errPrefix, errs, valTag, name, customName) {
|
|
679 |
if v.validateField(topStruct, currentStruct, current, typ, kind, errPrefix, nsPrefix, errs, valTag, name, customName) {
|
640 | 680 |
return
|
641 | 681 |
}
|
642 | 682 |
}
|
|
646 | 686 |
// or panic ;)
|
647 | 687 |
switch kind {
|
648 | 688 |
case reflect.Slice, reflect.Array:
|
649 | |
v.traverseSlice(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name, customName, partial, exclude, includeExclude, nil)
|
|
689 |
v.traverseSlice(topStruct, currentStruct, current, errPrefix, nsPrefix, errs, diveSubTag, name, customName, partial, exclude, includeExclude, nil)
|
650 | 690 |
case reflect.Map:
|
651 | |
v.traverseMap(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name, customName, partial, exclude, includeExclude, nil)
|
|
691 |
v.traverseMap(topStruct, currentStruct, current, errPrefix, nsPrefix, errs, diveSubTag, name, customName, partial, exclude, includeExclude, nil)
|
652 | 692 |
default:
|
653 | 693 |
// throw error, if not a slice or map then should not have gotten here
|
654 | 694 |
// bad dive tag
|
|
658 | 698 |
}
|
659 | 699 |
|
660 | 700 |
// traverseSlice traverses a Slice or Array's elements and passes them to traverseField for validation
|
661 | |
func (v *Validate) traverseSlice(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag, name, customName string, partial bool, exclude bool, includeExclude map[string]*struct{}, cTag *cachedTag) {
|
|
701 |
func (v *Validate) traverseSlice(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, tag, name, customName string, partial bool, exclude bool, includeExclude map[string]*struct{}, cTag *cachedTag) {
|
662 | 702 |
|
663 | 703 |
for i := 0; i < current.Len(); i++ {
|
664 | |
v.traverseField(topStruct, currentStruct, current.Index(i), errPrefix, errs, false, tag, fmt.Sprintf(arrayIndexFieldName, name, i), fmt.Sprintf(arrayIndexFieldName, customName, i), partial, exclude, includeExclude, cTag)
|
|
704 |
v.traverseField(topStruct, currentStruct, current.Index(i), errPrefix, nsPrefix, errs, false, tag, fmt.Sprintf(arrayIndexFieldName, name, i), fmt.Sprintf(arrayIndexFieldName, customName, i), partial, exclude, includeExclude, cTag)
|
665 | 705 |
}
|
666 | 706 |
}
|
667 | 707 |
|
668 | 708 |
// traverseMap traverses a map's elements and passes them to traverseField for validation
|
669 | |
func (v *Validate) traverseMap(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag, name, customName string, partial bool, exclude bool, includeExclude map[string]*struct{}, cTag *cachedTag) {
|
|
709 |
func (v *Validate) traverseMap(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, tag, name, customName string, partial bool, exclude bool, includeExclude map[string]*struct{}, cTag *cachedTag) {
|
670 | 710 |
|
671 | 711 |
for _, key := range current.MapKeys() {
|
672 | |
v.traverseField(topStruct, currentStruct, current.MapIndex(key), errPrefix, errs, false, tag, fmt.Sprintf(mapIndexFieldName, name, key.Interface()), fmt.Sprintf(mapIndexFieldName, customName, key.Interface()), partial, exclude, includeExclude, cTag)
|
|
712 |
v.traverseField(topStruct, currentStruct, current.MapIndex(key), errPrefix, nsPrefix, errs, false, tag, fmt.Sprintf(mapIndexFieldName, name, key.Interface()), fmt.Sprintf(mapIndexFieldName, customName, key.Interface()), partial, exclude, includeExclude, cTag)
|
673 | 713 |
}
|
674 | 714 |
}
|
675 | 715 |
|
676 | 716 |
// validateField validates a field based on the provided tag's key and param values and returns true if there is an error or false if all ok
|
677 | |
func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, currentType reflect.Type, currentKind reflect.Kind, errPrefix string, errs ValidationErrors, valTag *tagVals, name, customName string) bool {
|
|
717 |
func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, currentType reflect.Type, currentKind reflect.Kind, errPrefix string, nsPrefix string, errs ValidationErrors, valTag *tagVals, name, customName string) bool {
|
678 | 718 |
|
679 | 719 |
var valFunc Func
|
680 | 720 |
var ok bool
|
|
697 | 737 |
errTag += orSeparator + val[0]
|
698 | 738 |
}
|
699 | 739 |
|
|
740 |
ns := errPrefix + name
|
|
741 |
|
700 | 742 |
if valTag.isAlias {
|
701 | |
errs[errPrefix+name] = &FieldError{
|
702 | |
Name: customName,
|
703 | |
Field: name,
|
704 | |
Tag: valTag.tag,
|
705 | |
ActualTag: errTag[1:],
|
706 | |
Value: current.Interface(),
|
707 | |
Type: currentType,
|
708 | |
Kind: currentKind,
|
|
743 |
errs[ns] = &FieldError{
|
|
744 |
FieldNamespace: ns,
|
|
745 |
NameNamespace: nsPrefix + customName,
|
|
746 |
Name: customName,
|
|
747 |
Field: name,
|
|
748 |
Tag: valTag.tag,
|
|
749 |
ActualTag: errTag[1:],
|
|
750 |
Value: current.Interface(),
|
|
751 |
Type: currentType,
|
|
752 |
Kind: currentKind,
|
709 | 753 |
}
|
710 | 754 |
} else {
|
711 | 755 |
errs[errPrefix+name] = &FieldError{
|
712 | |
Name: customName,
|
713 | |
Field: name,
|
714 | |
Tag: errTag[1:],
|
715 | |
ActualTag: errTag[1:],
|
716 | |
Value: current.Interface(),
|
717 | |
Type: currentType,
|
718 | |
Kind: currentKind,
|
|
756 |
FieldNamespace: ns,
|
|
757 |
NameNamespace: nsPrefix + customName,
|
|
758 |
Name: customName,
|
|
759 |
Field: name,
|
|
760 |
Tag: errTag[1:],
|
|
761 |
ActualTag: errTag[1:],
|
|
762 |
Value: current.Interface(),
|
|
763 |
Type: currentType,
|
|
764 |
Kind: currentKind,
|
719 | 765 |
}
|
720 | 766 |
}
|
721 | 767 |
|
|
731 | 777 |
return false
|
732 | 778 |
}
|
733 | 779 |
|
734 | |
errs[errPrefix+name] = &FieldError{
|
735 | |
Name: customName,
|
736 | |
Field: name,
|
737 | |
Tag: valTag.tag,
|
738 | |
ActualTag: valTag.tagVals[0][0],
|
739 | |
Value: current.Interface(),
|
740 | |
Param: valTag.tagVals[0][1],
|
741 | |
Type: currentType,
|
742 | |
Kind: currentKind,
|
|
780 |
ns := errPrefix + name
|
|
781 |
|
|
782 |
errs[ns] = &FieldError{
|
|
783 |
FieldNamespace: ns,
|
|
784 |
NameNamespace: nsPrefix + customName,
|
|
785 |
Name: customName,
|
|
786 |
Field: name,
|
|
787 |
Tag: valTag.tag,
|
|
788 |
ActualTag: valTag.tagVals[0][0],
|
|
789 |
Value: current.Interface(),
|
|
790 |
Param: valTag.tagVals[0][1],
|
|
791 |
Type: currentType,
|
|
792 |
Kind: currentKind,
|
743 | 793 |
}
|
744 | 794 |
|
745 | 795 |
return true
|