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{}
|