Home > Software engineering >  Gin Gonic Custom Error Message Fails When Invalid Data Sent
Gin Gonic Custom Error Message Fails When Invalid Data Sent

Time:10-03

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": "[email protected]",
    "name": "John Doe",
    "mobile_country_code": 1,
    "mobile": 1234567
}

but sending an invalid type

{
    "email": "[email protected]",
    "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: How to assert error type json.UnmarshalTypeError when caught by gin c.BindJSON however the answers do not make sense.

CodePudding user response:

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

CodePudding user response:

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.

  • Related