Skip to content

Commit 127a6b2

Browse files
committed
Make it possible to create custom errors
1 parent d95271a commit 127a6b2

File tree

5 files changed

+218
-180
lines changed

5 files changed

+218
-180
lines changed

create_error.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package laravalidate
2+
3+
import "sort"
4+
5+
func CreateGoError(errors map[string]string) error {
6+
return createCustomError(GoMode, errors)
7+
}
8+
9+
func CreateJsonError(errors map[string]string) error {
10+
return createCustomError(JsonMode, errors)
11+
}
12+
13+
func createCustomError(mode Mode, errors map[string]string) error {
14+
fieldErrors := []FieldErrors{}
15+
for key, message := range errors {
16+
fieldErrors = append(fieldErrors, FieldErrors{
17+
Path: key,
18+
Errors: []FieldValidatorError{{
19+
Rule: "custom",
20+
Message: message,
21+
}},
22+
})
23+
}
24+
25+
sort.Slice(fieldErrors, func(i, j int) bool {
26+
return fieldErrors[i].Path < fieldErrors[j].Path
27+
})
28+
29+
return &ValidationError{
30+
Mode: mode,
31+
Language: nil, // Maybe we should do something with this?
32+
Errors: fieldErrors,
33+
}
34+
}

error.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ func (v *ValidationError) Error() string {
2323
}
2424

2525
type FieldErrors struct {
26-
Path string `json:"goPath"`
27-
JsonPath string `json:"jsonPath"`
28-
Errors []FieldValidatorError `json:"errors"`
26+
Path string `json:"path"`
27+
Errors []FieldValidatorError `json:"errors"`
2928
}
3029

3130
type FieldValidatorError struct {
@@ -73,9 +72,6 @@ func (e *ValidationError) ToLaravelError() *LaravelValidationError {
7372

7473
for _, entry := range e.Errors {
7574
path := entry.Path
76-
if e.Mode == JsonMode {
77-
path = entry.JsonPath
78-
}
7975

8076
errorMessages := []string{}
8177
for _, validatorError := range entry.Errors {

laravalidate.go

Lines changed: 8 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,14 @@ func (v *Validator) Validate(stack Stack, value *reflect.Value, valueType reflec
260260
}
261261

262262
goPath, jsonPath := stack.ToPaths()
263+
path := goPath
264+
if v.mode == JsonMode {
265+
path = jsonPath
266+
}
267+
263268
v.errors = append(v.errors, FieldErrors{
264-
Path: goPath,
265-
JsonPath: jsonPath,
266-
Errors: errors,
269+
Path: path,
270+
Errors: errors,
267271
})
268272
}
269273

@@ -426,7 +430,7 @@ func (v *Validator) field(stack Stack, path string) *Needle {
426430
pathParts = append(pathParts, part)
427431
}
428432

429-
if relativity == 0 || relativity > len(stack) {
433+
if relativity == 0 || len(stack) == 0 || relativity > len(stack) {
430434
// Absolute path
431435
return resolveWithValue(v.inputValue, pathParts)
432436
}
@@ -439,170 +443,3 @@ func (v *Validator) field(stack Stack, path string) *Needle {
439443

440444
return resolveWithValue(*stackElement.Parent, pathParts)
441445
}
442-
443-
func resolveWithValue(value reflect.Value, path []string) *Needle {
444-
if len(path) == 0 {
445-
valueType := value.Type()
446-
447-
return &Needle{
448-
Value: &value,
449-
Type: valueType,
450-
}
451-
}
452-
453-
for value.Kind() == reflect.Ptr {
454-
if value.IsNil() {
455-
return resolveWithType(value.Type().Elem(), path)
456-
}
457-
value = value.Elem()
458-
}
459-
460-
needle := path[0]
461-
path = path[1:]
462-
463-
if needle == "" {
464-
return nil
465-
}
466-
467-
kind := value.Kind()
468-
switch kind {
469-
case reflect.Struct:
470-
field, ok := value.Type().FieldByName(needle)
471-
if !ok {
472-
return nil
473-
}
474-
475-
return resolveWithValue(value.FieldByIndex(field.Index), path)
476-
case reflect.Slice, reflect.Array:
477-
needleNumber, err := strconv.Atoi(needle)
478-
if err != nil {
479-
return nil
480-
}
481-
482-
if kind == reflect.Slice && value.IsNil() {
483-
return resolveWithType(value.Type().Elem(), path)
484-
}
485-
486-
if needleNumber < 0 || needleNumber >= value.Len() {
487-
return nil
488-
}
489-
490-
return resolveWithValue(value.Index(needleNumber), path)
491-
case reflect.Map:
492-
var key reflect.Value
493-
keySet := false
494-
valueType := value.Type()
495-
keyKind := valueType.Key().Kind()
496-
497-
switch keyKind {
498-
case reflect.Bool:
499-
if needle == "true" {
500-
key = reflect.ValueOf(true)
501-
keySet = true
502-
} else if needle == "false" {
503-
key = reflect.ValueOf(false)
504-
keySet = true
505-
}
506-
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
507-
index, err := strconv.ParseInt(needle, 10, 64)
508-
if err != nil {
509-
return nil
510-
}
511-
512-
switch keyKind {
513-
case reflect.Int:
514-
key = reflect.ValueOf(int(index))
515-
case reflect.Int8:
516-
if int64(int8(index)) != index {
517-
return nil
518-
}
519-
key = reflect.ValueOf(int8(index))
520-
case reflect.Int16:
521-
if int64(int16(index)) != index {
522-
return nil
523-
}
524-
key = reflect.ValueOf(int16(index))
525-
case reflect.Int32:
526-
if int64(int32(index)) != index {
527-
return nil
528-
}
529-
key = reflect.ValueOf(int32(index))
530-
case reflect.Int64:
531-
key = reflect.ValueOf(int64(index))
532-
}
533-
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
534-
index, err := strconv.ParseUint(needle, 10, 64)
535-
if err != nil {
536-
return nil
537-
}
538-
539-
switch keyKind {
540-
case reflect.Uint:
541-
key = reflect.ValueOf(int(index))
542-
case reflect.Int8:
543-
if uint64(uint8(index)) != index {
544-
return nil
545-
}
546-
key = reflect.ValueOf(int8(index))
547-
case reflect.Uint16:
548-
if uint64(uint16(index)) != index {
549-
return nil
550-
}
551-
key = reflect.ValueOf(int16(index))
552-
case reflect.Uint32:
553-
if uint64(uint32(index)) != index {
554-
return nil
555-
}
556-
key = reflect.ValueOf(int32(index))
557-
case reflect.Uint64:
558-
key = reflect.ValueOf(int64(index))
559-
}
560-
case reflect.String:
561-
key = reflect.ValueOf(needle)
562-
keySet = true
563-
}
564-
565-
if !keySet {
566-
return nil
567-
}
568-
field := value.MapIndex(key)
569-
if field.Kind() == reflect.Invalid {
570-
return resolveWithType(valueType.Elem(), path)
571-
}
572-
573-
return resolveWithValue(field, path)
574-
default:
575-
return nil
576-
}
577-
}
578-
579-
func resolveWithType(valueType reflect.Type, path []string) *Needle {
580-
if len(path) == 0 {
581-
return &Needle{
582-
Type: valueType,
583-
}
584-
}
585-
586-
for valueType.Kind() == reflect.Ptr {
587-
valueType = valueType.Elem()
588-
}
589-
590-
needle := path[0]
591-
path = path[1:]
592-
593-
if needle == "" {
594-
return nil
595-
}
596-
597-
kind := valueType.Kind()
598-
switch kind {
599-
case reflect.Struct:
600-
field, ok := valueType.FieldByName(needle)
601-
if !ok {
602-
return nil
603-
}
604-
return resolveWithType(field.Type, path)
605-
}
606-
607-
return nil
608-
}

laravalidate_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,7 @@ func TestErrorMessages(t *testing.T) {
134134
assert.Len(t, typedErr.Errors, 1)
135135

136136
firstErr := typedErr.Errors[0]
137-
assert.Equal(t, "Message", firstErr.Path)
138-
assert.Equal(t, "message", firstErr.JsonPath)
137+
assert.Equal(t, "message", firstErr.Path)
139138
assert.Len(t, firstErr.Errors, 1)
140139

141140
firstValidatorErr := firstErr.Errors[0]
@@ -178,7 +177,6 @@ func TestCustomErrorMessages(t *testing.T) {
178177

179178
firstErr := typedErr.Errors[0]
180179
assert.Equal(t, "Inner.0.Inner2.Inner3", firstErr.Path)
181-
assert.Equal(t, "Inner.0.Inner2.Inner3", firstErr.JsonPath)
182180
assert.Len(t, firstErr.Errors, 1)
183181

184182
firstValidatorErr := firstErr.Errors[0]

0 commit comments

Comments
 (0)