3

Gin Request 绑定失败时自定义Message

 3 years ago
source link: https://peon.top/show/4
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Gin Request 绑定失败时自定义Message蜂鸟的小窝
Gin Request 绑定失败时自定义Message

    我用GIN,做为我的WEB框架,并且一直使用它。一直以来有一个问题一直困绕着我,在GIN的 Controller 执行其间,如果 context.bind 失败了,它的 error 对象会返回一段英文的错误码,我看着很难受,但却不知道怎么改。于是我寻遍大江南北,发现有一些博文有讲这个问题,但我一知半解,看的有点不明不白。然而就在今天,我终于尝试走出了这个困境。

    首先,我发现Gin内部的验证器用的是 validate 项目,从其代码上看,似乎bind 所返回的 error 中还带着一些其它信息,只是因为其返回标准的 error接口 被隐藏了。

    经过对源码的一番研究,我发现,其 error 对象实现了另一个接口 validator.ValidationErrors ,我抱着试试看的心情对它进行了断言。然后我执行了一它,发现断言成功了,这让我更有信心了。

    因以前用 Laravel 时感觉其 function messages() {} 的函数很好用,于是我也动手实现了一下。

    首先,我定义了一个 TestingRequest 代码如下:

type TestingRequest struct {
	Phone string `form:"phone" binding:"required"`
}

    从代码中我们可以看到 Phone 这个字段被设置成了必填参数。当然在这时,我们去 controller 中对于执行 Bind 操作,它一定会返回给你一段英文的错误消息。

    这时候我要为 TestingRequest 定义了一个 Map,Map中存放的是我对每一个规则所对应的自定义消息

func (p *TestingRequest) Messages() map[string]string {
	return map[string]string{
		"Phone.required": "请填写电话号码",
	}
}

    这时,我只需要在一个适当的时候,将 Bind 返回出来的 error 匹配 map 返回出来就可以了,于是我定义了一个函数

func ErrorMessage(err error, message Message) error {
	//	将 err 断言为 ValidationErrors
	//	若此时断言成功,则可以获得更多的参数
	fes, ok := err.(validator.ValidationErrors)
	if !ok {
		return err
	}

	//	查找当前字段当前规则的 Message ,如果没有则返回原来的 Message
	msg, ok := message.Find(fmt.Sprintf("%s.%s", fes[0].Field(), fes[0].Tag()))
	if !ok {
		return err
	}

	//	如果有则返回当前的 Message
	return errors.New(msg)
}

好吧,都注释在上面了,也懒得再解释了,大概就是将 error 断言为 validator.ValidationErrors ,当其成功断言时,获取其 Field() 与 Tag() 两个方法的返回值 ,并到原本在 TestingRequest 中定义的 Map 中查找该消息,若有,则创建一个错误对象,将其返回出来,这时候在 Controller ,你可以愉快的使用 ErrorMessage(Bind(),reqeuest.Message()).Error() 来返回你自定义的错误了。

    当然该方法也是我今天才尝试出来的,一定会有一些缺陷。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK