Gin Gonic在发送无效数据时自定义错误消息失败。

huangapple go评论115阅读模式
英文:

Gin Gonic Custom Error Message Fails When Invalid Data Sent

问题

Validator结构体

  1. type RegisterValidator struct {
  2. Name string `form:"name" json:"name" binding:"required,min=4,max=50"`
  3. Email string `form:"email" json:"email" binding:"required,email,min=4,max=50"`
  4. Password string `form:"password" json:"password" binding:"required,min=8,max=50"`
  5. MobileCountryCode int `form:"mobile_country_code" json:"mobile_country_code" binding:"required,gte=2,lt=5"`
  6. Mobile int `form:"mobile" json:"mobile" binding:"required,gte=5,lt=15"`
  7. UserModel users.User `json:"-"`
  8. }

将自定义错误格式化如下:

  1. type CustomError struct {
  2. Errors map[string]interface{} `json:"errors"`
  3. }
  4. func NewValidatorError(err error) CustomError {
  5. res := CustomError{}
  6. res.Errors = make(map[string]interface{})
  7. errs := err.(validator.ValidationErrors)
  8. for _, v := range errs {
  9. param := v.Param()
  10. field := v.Field()
  11. tag := v.Tag()
  12. if param != "" {
  13. res.Errors[field] = fmt.Sprintf("{%v: %v}", tag, param)
  14. } else {
  15. res.Errors[field] = fmt.Sprintf("{key: %v}", tag)
  16. }
  17. }
  18. return res
  19. }

当发送的数据为

  1. {
  2. "email": "me@example.com",
  3. "name": "John Doe",
  4. "mobile_country_code": 1,
  5. "mobile": 1234567
  6. }

时可以正常工作。

但是当发送一个无效的类型时

  1. {
  2. "email": "me@example.com",
  3. "name": "John Doe",
  4. "mobile_country_code": "1",
  5. "mobile": 1234567
  6. }

会抛出错误interface conversion: error is *json.UnmarshalTypeError, not validator.ValidationErrors

这个问题与此问题相关:https://stackoverflow.com/questions/64278486/how-to-assert-error-type-json-unmarshaltypeerror-when-caught-by-gin-c-bindjson
然而,答案并不合理。

英文:

Validator struct

  1. type RegisterValidator struct {
  2. Name string `form:"name" json:"name" binding:"required,min=4,max=50"`
  3. Email string `form:"email" json:"email" binding:"required,email,min=4,max=50"`
  4. Password string `form:"password" json:"password" binding:"required,min=8,max=50"`
  5. MobileCountryCode int `form:"mobile_country_code" json:"mobile_country_code" binding:"required,gte=2,lt=5"`
  6. Mobile int `form:"mobile" json:"mobile" binding:"required,gte=5,lt=15"`
  7. UserModel users.User `json:"-"`
  8. }

Formatting a custom error as below:

  1. type CustomError struct {
  2. Errors map[string]interface{} `json:"errors"`
  3. }
  4. func NewValidatorError(err error) CustomError {
  5. res := CustomError{}
  6. res.Errors = make(map[string]interface{})
  7. errs := err.(validator.ValidationErrors)
  8. for _, v := range errs {
  9. param := v.Param()
  10. field := v.Field()
  11. tag := v.Tag()
  12. if param != "" {
  13. res.Errors[field] = fmt.Sprintf("{%v: %v}", tag, param)
  14. } else {
  15. res.Errors[field] = fmt.Sprintf("{key: %v}", tag)
  16. }
  17. }
  18. return res
  19. }

works when data sent is

  1. {
  2. "email": "me@example.com",
  3. "name": "John Doe",
  4. "mobile_country_code": 1,
  5. "mobile": 1234567
  6. }

but sending an invalid type

  1. {
  2. "email": "me@example.com",
  3. "name": "John Doe",
  4. "mobile_country_code": "1",
  5. "mobile": 1234567
  6. }

throws the error interface conversion: error is *json.UnmarshalTypeError, not validator.ValidationErrors

This question is related to this one: https://stackoverflow.com/questions/64278486/how-to-assert-error-type-json-unmarshaltypeerror-when-caught-by-gin-c-bindjson
however the answers do not make sense.

答案1

得分: 2

根据异常提示,以下代码行无法进行类型转换:

  1. errs := err.(validator.ValidationErrors)

函数中传入了一个不是 *validator.ValidationErrors 类型的错误。

因此,要么确保其他类型的错误不会传递给 NewValidatorError 函数,要么进行更安全的类型检查,例如:

  1. errs, ok := err.(validator.ValidationErrors)
  2. if !ok {
  3. // 处理其他错误类型
  4. }

更多信息:A Tour of Go - 类型断言A Tour of Go - 类型切换

英文:

As the exception suggests, the following line failed type conversion

  1. errs := err.(validator.ValidationErrors)

A different type of error must have got passed into the function that is not validator.ValidationErrors.

So either make sure other errors won't be passed into NewValidatorError. Or do a safer type check like:

  1. errs, ok := err.(validator.ValidationErrors)
  2. if !ok {
  3. // handles other err type
  4. }

More info: A Tour of Go - type assertions, A Tour of Go - type switches

答案2

得分: -1

我为UnmarshalTypeError添加了一个检查,代码如下:

  1. if reflect.TypeOf(err).Elem().String() == "json.UnmarshalTypeError" {
  2. errs := err.(*json.UnmarshalTypeError)
  3. res.Errors[errs.Field] = fmt.Sprintf("{key: %v}", errs.Error())
  4. return res
  5. }
  6. errs := err.(validator.ValidationErrors)

我猜Golang在对JSON进行类型提示时是严格的。它必须是精确的类型,否则会抛出UnmarshalTypeError错误。

英文:

I added a check for the UnmarshalTypeError as below:

  1. if reflect.TypeOf(err).Elem().String() == "json.UnmarshalTypeError" {
  2. errs := err.(*json.UnmarshalTypeError)
  3. res.Errors[errs.Field] = fmt.Sprintf("{key: %v}", errs.Error())
  4. return res
  5. }
  6. errs := err.(validator.ValidationErrors)

I guess Golang is strict when json is type-hinted. It has to be the exact type otherwise it will throw an UnmarshalTypeError error.

huangapple
  • 本文由 发表于 2021年9月29日 04:08:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/69367914.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定