forked from go-ozzo/ozzo-validation
-
Notifications
You must be signed in to change notification settings - Fork 6
/
error.go
180 lines (153 loc) · 3.81 KB
/
error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright 2016 Qiang Xue. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package validation
import (
"bytes"
"encoding/json"
"fmt"
"sort"
"strings"
"text/template"
)
type (
// Error interface represents an validation error
Error interface {
Error() string
Code() string
Message() string
SetMessage(string) Error
Params() map[string]interface{}
SetParams(map[string]interface{}) Error
}
// ErrorObject is the default validation error
// that implements the Error interface.
ErrorObject struct {
code string
message string
params map[string]interface{}
}
// Errors represents the validation errors that are indexed by struct field names, map or slice keys.
// values are Error or Errors (for map, slice and array error value is Errors).
Errors map[string]error
// InternalError represents an error that should NOT be treated as a validation error.
InternalError interface {
error
InternalError() error
}
internalError struct {
error
}
)
// NewInternalError wraps a given error into an InternalError.
func NewInternalError(err error) InternalError {
return internalError{error: err}
}
// InternalError returns the actual error that it wraps around.
func (e internalError) InternalError() error {
return e.error
}
// SetCode set the error's translation code.
func (e ErrorObject) SetCode(code string) Error {
e.code = code
return e
}
// Code get the error's translation code.
func (e ErrorObject) Code() string {
return e.code
}
// SetParams set the error's params.
func (e ErrorObject) SetParams(params map[string]interface{}) Error {
e.params = params
return e
}
// AddParam add parameter to the error's parameters.
func (e ErrorObject) AddParam(name string, value interface{}) Error {
if e.params == nil {
e.params = make(map[string]interface{})
}
e.params[name] = value
return e
}
// Params returns the error's params.
func (e ErrorObject) Params() map[string]interface{} {
return e.params
}
// SetMessage set the error's message.
func (e ErrorObject) SetMessage(message string) Error {
e.message = message
return e
}
// Message return the error's message.
func (e ErrorObject) Message() string {
return e.message
}
// Error returns the error message.
func (e ErrorObject) Error() string {
if len(e.params) == 0 {
return e.message
}
res := bytes.Buffer{}
_ = template.Must(template.New("err").Parse(e.message)).Execute(&res, e.params)
return res.String()
}
// Error returns the error string of Errors.
func (es Errors) Error() string {
if len(es) == 0 {
return ""
}
keys := make([]string, len(es))
i := 0
for key := range es {
keys[i] = key
i++
}
sort.Strings(keys)
var s strings.Builder
for i, key := range keys {
if i > 0 {
s.WriteString("; ")
}
if errs, ok := es[key].(Errors); ok {
_, _ = fmt.Fprintf(&s, "%v: (%v)", key, errs)
} else {
_, _ = fmt.Fprintf(&s, "%v: %v", key, es[key].Error())
}
}
s.WriteString(".")
return s.String()
}
// MarshalJSON converts the Errors into a valid JSON.
func (es Errors) MarshalJSON() ([]byte, error) {
errs := map[string]interface{}{}
for key, err := range es {
if ms, ok := err.(json.Marshaler); ok {
errs[key] = ms
} else {
errs[key] = err.Error()
}
}
return json.Marshal(errs)
}
// Filter removes all nils from Errors and returns back the updated Errors as an error.
// If the length of Errors becomes 0, it will return nil.
func (es Errors) Filter() error {
for key, value := range es {
if value == nil {
delete(es, key)
}
}
if len(es) == 0 {
return nil
}
return es
}
// NewError create new validation error.
func NewError(code, message string) Error {
return ErrorObject{
code: code,
message: message,
}
}
// Assert that our ErrorObject implements the Error interface.
var _ Error = ErrorObject{}