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

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

Gin Gonic Custom Error Message Fails When Invalid Data Sent

问题

Validator结构体

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

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

type CustomError struct {
	Errors map[string]interface{} `json:"errors"`
}

func NewValidatorError(err error) CustomError {
	res := CustomError{}
	res.Errors = make(map[string]interface{})
	errs := err.(validator.ValidationErrors)

	for _, v := range errs {
		param := v.Param()
		field := v.Field()
		tag := v.Tag()

		if param != "" {
			res.Errors[field] = fmt.Sprintf("{%v: %v}", tag, param)
		} else {
			res.Errors[field] = fmt.Sprintf("{key: %v}", tag)
		}
	}

	return res
}

当发送的数据为

{
    "email": "me@example.com",
    "name": "John Doe",
    "mobile_country_code": 1,
    "mobile": 1234567
}

时可以正常工作。

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

{
    "email": "me@example.com",
    "name": "John Doe",
    "mobile_country_code": "1",
    "mobile": 1234567
}

会抛出错误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

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

Formatting a custom error as below:

type CustomError struct {
	Errors map[string]interface{} `json:"errors"`
}

func NewValidatorError(err error) CustomError {
	res := CustomError{}
	res.Errors = make(map[string]interface{})
	errs := err.(validator.ValidationErrors)

	for _, v := range errs {
		param := v.Param()
		field := v.Field()
		tag := v.Tag()

		if param != "" {
			res.Errors[field] = fmt.Sprintf("{%v: %v}", tag, param)
		} else {
			res.Errors[field] = fmt.Sprintf("{key: %v}", tag)
		}
	}

	return res
}

works when data sent is

{
    "email": "me@example.com",
    "name": "John Doe",
    "mobile_country_code": 1,
    "mobile": 1234567
}

but sending an invalid type

{
    "email": "me@example.com",
    "name": "John Doe",
    "mobile_country_code": "1",
    "mobile": 1234567
}

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

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

errs := err.(validator.ValidationErrors)

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

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

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

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

英文:

As the exception suggests, the following line failed type conversion

    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:

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

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

答案2

得分: -1

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

if reflect.TypeOf(err).Elem().String() == "json.UnmarshalTypeError" {
    errs := err.(*json.UnmarshalTypeError)
    res.Errors[errs.Field] = fmt.Sprintf("{key: %v}", errs.Error())

    return res
}

errs := err.(validator.ValidationErrors)

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

英文:

I added a check for the UnmarshalTypeError as below:

	if reflect.TypeOf(err).Elem().String() == "json.UnmarshalTypeError" {
		errs := err.(*json.UnmarshalTypeError)
		res.Errors[errs.Field] = fmt.Sprintf("{key: %v}", errs.Error())

		return res
	}

	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:

确定