Wil*_*zzi 5 arrays error-handling json go
我有一系列错误(错误类型),但是当我尝试以 JSON 格式返回客户端时,它到达时为空。
它是这样创建的:
var (
ErrEmptyName = errors.New("Nome não pode ser vázio")
ErrInvalidType = errors.New("Tipo de pessoa inválido")
)
func (p Person) Validate() []error {
var errors []error
if govalidator.IsNull(p.Name) {
errors = append(errors, ErrEmptyName)
}
if p.Type != "F" && p.Type != "J" {
errors = append(errors, ErrInvalidType)
}
return errors
)
Run Code Online (Sandbox Code Playgroud)
在我的控制器中:
err := person.Validate()
c.JSON(422, gin.H{"errors" : err})
Run Code Online (Sandbox Code Playgroud)
我的输出:
{"errors":"[{}]"}
Run Code Online (Sandbox Code Playgroud)
该error类型是具有单个的接口Error()方法,但它不是特殊的json包(Error()方法不被调用就可以了)。
但是,error值可以保存静态类型的值,这些值可以很好地编组,或者它们可以通过实现json.Marshaler. 简单error地string通过调用它的Error()方法来转换一个to意味着我们不遵守自定义封送处理逻辑。
所以我建议创建我们自己的错误切片类型,我们可以在其上实现我们的封送处理逻辑,它应该是:
json.Marshaler,如果是,则让它自行编组error.Error()“获取”一个string可以轻松编组的这是它的样子:
type JSONErrs []error
func (je JSONErrs) MarshalJSON() ([]byte, error) {
res := make([]interface{}, len(je))
for i, e := range je {
if _, ok := e.(json.Marshaler); ok {
res[i] = e // e knows how to marshal itself
} else {
res[i] = e.Error() // Fallback to the error string
}
}
return json.Marshal(res)
}
Run Code Online (Sandbox Code Playgroud)
这就是您可以使用它的方式:
err := person.Validate()
c.JSON(422, gin.H{"errors" : JSONErrs(err)})
Run Code Online (Sandbox Code Playgroud)
让我们测试一下我们的JSONErrs. 我们还使用自定义错误类型来实现自定义封送处理逻辑:
type MyErr struct{ line int }
func (me MyErr) Error() string { return "Invalid input!" }
func (me MyErr) MarshalJSON() ([]byte, error) {
return json.Marshal(
struct {
Type, Error string
AtLine int
}{"MyErr", me.Error(), me.line})
}
Run Code Online (Sandbox Code Playgroud)
和测试代码:
errs := []error{
errors.New("first"),
errors.New("second"),
MyErr{16},
}
data, err := json.Marshal(JSONErrs(errs))
fmt.Println(string(data), err)
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上试试):
["first","second",{"Type":"MyErr","Error":"Invalid input!","AtLine":16}] <nil>
Run Code Online (Sandbox Code Playgroud)
类型error是一个接口,它必须实现一个Error()以字符串形式返回错误消息的方法。这是在这里定义的: https: //golang.org/pkg/builtin/#error。类型之所以error是接口,是为了允许error可以进行类型转换的类型来检索更详细的信息。
fmt.Println和等函数log.Println会自动解析error类型以显示来自 的消息Error(),但 JSON 库却不会。解决此问题的最简单方法是将错误消息转换为[]errora[]string并对其进行编码。
下面是一些使用 for 循环执行此操作的示例代码。
errs := person.Validate()
strErrors := make([]string, len(errs))
for i, err := range errs {
strErrors[i] = err.Error()
}
c.JSON(422, gin.H{"errors" : strErrors})
Run Code Online (Sandbox Code Playgroud)