[英]How to assert error type json.UnmarshalTypeError when caught by gin c.BindJSON
I'm trying to catch binding errors with gin gonic and it's working fine for all validation errors from go-playground/validator/v10 but i'm having an issue catching errors when unmarshalling into the proper data type.我正在尝试使用 gin gonic 捕获绑定错误,并且对于来自 go-playground/validator/v10 的所有验证错误都可以正常工作,但是在解组为正确的数据类型时我遇到了捕获错误的问题。
Unsuccessful validation of a struct field will return a gin.ErrorTypeBind
Type of error when using validator tags ( required,...)使用验证器标签(必需,...)时,结构字段验证不成功将返回
gin.ErrorTypeBind
错误类型
but if i have a struct但如果我有一个结构
type Foo struct {
ID int `json:"id"`
Bar string `json:"bar"`
}
And the json i'm trying to pass is of a wrong format (passing a string instead of a number for id )我试图传递的 json 格式错误(传递字符串而不是 id 的数字)
{
"id":"string",
"bar":"foofofofo"
}
It will fail with an error json: cannot unmarshal string into Go struct field Foo.id of type int
它将失败并出现错误
json: cannot unmarshal string into Go struct field Foo.id of type int
It is still caught as a gin.ErrorTypeBind
in my handler as an error in binding but as i need to differentiate between validation error and unmarshalling error i'm having issues.它仍然在我的处理程序中作为
gin.ErrorTypeBind
被捕获为绑定错误,但由于我需要区分验证错误和解组错误,我遇到了问题。
I have tried Type casting on validaton error doesn't work for unmarshalling: e.Err.(validator.ValidationErrors)
will panic我尝试过在验证错误上进行类型转换不适用于解组:
e.Err.(validator.ValidationErrors)
会恐慌
or just errors.Is but this will not catch the error at all或者只是errors.Is,但这根本不会捕获错误
if errors.Is(e.Err, &json.UnmarshalTypeError{}) {
log.Println("Json binding error")
}
My goal in doing so is to return properly formatted error message to the user.我这样做的目标是向用户返回格式正确的错误消息。 It's currently working well for all the validation logic but i can't seem to make it work for json data where incorrect data would be sent to me.
它目前适用于所有验证逻辑,但我似乎无法使其适用于 json 数据,因为这些数据会发送给我不正确的数据。
any ideas?有任何想法吗?
edit:编辑:
adding example to reproduce:添加示例以重现:
package main
import (
"encoding/json"
"errors"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)
type Foo struct {
ID int `json:"id" binding:"required"`
Bar string `json:"bar"`
}
func FooEndpoint(c *gin.Context) {
var fooJSON Foo
err := c.BindJSON(&fooJSON)
if err != nil {
// caught and answer in the error MW
return
}
c.JSON(200, "test")
}
func main() {
api := gin.Default()
api.Use(ErrorMW())
api.POST("/foo", FooEndpoint)
api.Run(":5000")
}
func ErrorMW() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
if len(c.Errors) > 0 {
for _, e := range c.Errors {
switch e.Type {
case gin.ErrorTypeBind:
log.Println(e.Err)
var jsonErr json.UnmarshalTypeError
if errors.Is(e.Err, &jsonErr) {
log.Println("Json binding error")
}
// if errors.As(e.Err, &jsonErr) {
// log.Println("Json binding error")
// }
// in reality i'm making it panic.
// errs := e.Err.(validator.ValidationErrors)
errs, ok := e.Err.(validator.ValidationErrors)
if ok {
log.Println("error trying to cast validation type")
}
log.Println(errs)
status := http.StatusBadRequest
if c.Writer.Status() != http.StatusOK {
status = c.Writer.Status()
}
c.JSON(status, gin.H{"error": "error"})
default:
log.Println("other error")
}
}
if !c.Writer.Written() {
c.JSON(http.StatusInternalServerError, gin.H{"Error": "internal error"})
}
}
}
}
trying sending a post request with a body尝试发送带有正文的发布请求
{
"id":"rwerewr",
"bar":"string"
}
interface conversion: error is *json.UnmarshalTypeError, not validator.ValidationErrors
this will work:这将起作用:
{
"id":1,
"bar":"string"
}
and this will (rightfully ) return Key: 'Foo.ID' Error:Field validation for 'ID' failed on the 'required' tag
这将(正确地)返回
Key: 'Foo.ID' Error:Field validation for 'ID' failed on the 'required' tag
{ "bar":"string" } {“酒吧”:“字符串”}
I'm trying to catch binding errors with gin gonic and it's working fine for all validation errors from go-playground/validator/v10 but i'm having an issue catching errors when unmarshalling into the proper data type.我正在尝试使用gin gonic捕获绑定错误,并且对于来自go-playground / validator / v10的所有验证错误都可以正常工作,但是在将数据编组为正确的数据类型时遇到了捕获错误的问题。
Unsuccessful validation of a struct field will return a gin.ErrorTypeBind
Type of error when using validator tags ( required, ...)对结构字段的验证失败将返回
gin.ErrorTypeBind
使用验证器标签时的错误类型(必填,...)
but if i have a struct但是如果我有一个结构
type Foo struct {
ID int `json:"id"`
Bar string `json:"bar"`
}
And the json i'm trying to pass is of a wrong format (passing a string instead of a number for id )我尝试传递的json格式错误(传递字符串而不是id的数字)
{
"id":"string",
"bar":"foofofofo"
}
It will fail with an error json: cannot unmarshal string into Go struct field Foo.id of type int
它将失败并显示错误
json: cannot unmarshal string into Go struct field Foo.id of type int
It is still caught as a gin.ErrorTypeBind
in my handler as an error in binding but as i need to differentiate between validation error and unmarshalling error i'm having issues.它仍然被
gin.ErrorTypeBind
为我的处理程序中的gin.ErrorTypeBind
作为绑定错误,但是由于我需要区分验证错误和解组错误,所以我遇到了问题。
I have tried Type casting on validaton error doesn't work for unmarshalling : e.Err.(validator.ValidationErrors)
will panic我已经尝试过在validaton错误上进行类型转换,但无法进行解组:
e.Err.(validator.ValidationErrors)
会惊慌
or just errors.Is but this will not catch the error at all或只是错误。是,但这根本不会捕捉到错误
if errors.Is(e.Err, &json.UnmarshalTypeError{}) {
log.Println("Json binding error")
}
My goal in doing so is to return properly formatted error message to the user.我这样做的目的是将正确格式的错误消息返回给用户。 It's currently working well for all the validation logic but i can't seem to make it work for json data where incorrect data would be sent to me.
目前,对于所有验证逻辑而言,它都运行良好,但我似乎无法使其适用于json数据,在该数据中,不正确的数据会发送给我。
any ideas?有任何想法吗?
edit :编辑 :
adding example to reproduce :添加示例以重现:
package main
import (
"encoding/json"
"errors"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)
type Foo struct {
ID int `json:"id" binding:"required"`
Bar string `json:"bar"`
}
func FooEndpoint(c *gin.Context) {
var fooJSON Foo
err := c.BindJSON(&fooJSON)
if err != nil {
// caught and answer in the error MW
return
}
c.JSON(200, "test")
}
func main() {
api := gin.Default()
api.Use(ErrorMW())
api.POST("/foo", FooEndpoint)
api.Run(":5000")
}
func ErrorMW() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
if len(c.Errors) > 0 {
for _, e := range c.Errors {
switch e.Type {
case gin.ErrorTypeBind:
log.Println(e.Err)
var jsonErr json.UnmarshalTypeError
if errors.Is(e.Err, &jsonErr) {
log.Println("Json binding error")
}
// if errors.As(e.Err, &jsonErr) {
// log.Println("Json binding error")
// }
// in reality i'm making it panic.
// errs := e.Err.(validator.ValidationErrors)
errs, ok := e.Err.(validator.ValidationErrors)
if ok {
log.Println("error trying to cast validation type")
}
log.Println(errs)
status := http.StatusBadRequest
if c.Writer.Status() != http.StatusOK {
status = c.Writer.Status()
}
c.JSON(status, gin.H{"error": "error"})
default:
log.Println("other error")
}
}
if !c.Writer.Written() {
c.JSON(http.StatusInternalServerError, gin.H{"Error": "internal error"})
}
}
}
}
trying sending a post request with a body尝试发送带有正文的帖子请求
{
"id":"rwerewr",
"bar":"string"
}
interface conversion: error is *json.UnmarshalTypeError, not validator.ValidationErrors
this will work :这将工作:
{
"id":1,
"bar":"string"
}
and this will (rightfully ) return Key: 'Foo.ID' Error:Field validation for 'ID' failed on the 'required' tag
这将(正确地)返回
Key: 'Foo.ID' Error:Field validation for 'ID' failed on the 'required' tag
{ "bar":"string" } {“ bar”:“ string”}
I'm trying to catch binding errors with gin gonic and it's working fine for all validation errors from go-playground/validator/v10 but i'm having an issue catching errors when unmarshalling into the proper data type.我正在尝试使用gin gonic捕获绑定错误,并且对于来自go-playground / validator / v10的所有验证错误都可以正常工作,但是在将数据编组为正确的数据类型时遇到了捕获错误的问题。
Unsuccessful validation of a struct field will return a gin.ErrorTypeBind
Type of error when using validator tags ( required, ...)对结构字段的验证失败将返回
gin.ErrorTypeBind
使用验证器标签时的错误类型(必填,...)
but if i have a struct但是如果我有一个结构
type Foo struct {
ID int `json:"id"`
Bar string `json:"bar"`
}
And the json i'm trying to pass is of a wrong format (passing a string instead of a number for id )我尝试传递的json格式错误(传递字符串而不是id的数字)
{
"id":"string",
"bar":"foofofofo"
}
It will fail with an error json: cannot unmarshal string into Go struct field Foo.id of type int
它将失败并显示错误
json: cannot unmarshal string into Go struct field Foo.id of type int
It is still caught as a gin.ErrorTypeBind
in my handler as an error in binding but as i need to differentiate between validation error and unmarshalling error i'm having issues.它仍然被
gin.ErrorTypeBind
为我的处理程序中的gin.ErrorTypeBind
作为绑定错误,但是由于我需要区分验证错误和解组错误,所以我遇到了问题。
I have tried Type casting on validaton error doesn't work for unmarshalling : e.Err.(validator.ValidationErrors)
will panic我已经尝试过在validaton错误上进行类型转换,但无法进行解组:
e.Err.(validator.ValidationErrors)
会惊慌
or just errors.Is but this will not catch the error at all或只是错误。是,但这根本不会捕捉到错误
if errors.Is(e.Err, &json.UnmarshalTypeError{}) {
log.Println("Json binding error")
}
My goal in doing so is to return properly formatted error message to the user.我这样做的目的是将正确格式的错误消息返回给用户。 It's currently working well for all the validation logic but i can't seem to make it work for json data where incorrect data would be sent to me.
目前,对于所有验证逻辑而言,它都运行良好,但我似乎无法使其适用于json数据,在该数据中,不正确的数据会发送给我。
any ideas?有任何想法吗?
edit :编辑 :
adding example to reproduce :添加示例以重现:
package main
import (
"encoding/json"
"errors"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)
type Foo struct {
ID int `json:"id" binding:"required"`
Bar string `json:"bar"`
}
func FooEndpoint(c *gin.Context) {
var fooJSON Foo
err := c.BindJSON(&fooJSON)
if err != nil {
// caught and answer in the error MW
return
}
c.JSON(200, "test")
}
func main() {
api := gin.Default()
api.Use(ErrorMW())
api.POST("/foo", FooEndpoint)
api.Run(":5000")
}
func ErrorMW() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
if len(c.Errors) > 0 {
for _, e := range c.Errors {
switch e.Type {
case gin.ErrorTypeBind:
log.Println(e.Err)
var jsonErr json.UnmarshalTypeError
if errors.Is(e.Err, &jsonErr) {
log.Println("Json binding error")
}
// if errors.As(e.Err, &jsonErr) {
// log.Println("Json binding error")
// }
// in reality i'm making it panic.
// errs := e.Err.(validator.ValidationErrors)
errs, ok := e.Err.(validator.ValidationErrors)
if ok {
log.Println("error trying to cast validation type")
}
log.Println(errs)
status := http.StatusBadRequest
if c.Writer.Status() != http.StatusOK {
status = c.Writer.Status()
}
c.JSON(status, gin.H{"error": "error"})
default:
log.Println("other error")
}
}
if !c.Writer.Written() {
c.JSON(http.StatusInternalServerError, gin.H{"Error": "internal error"})
}
}
}
}
trying sending a post request with a body尝试发送带有正文的帖子请求
{
"id":"rwerewr",
"bar":"string"
}
interface conversion: error is *json.UnmarshalTypeError, not validator.ValidationErrors
this will work :这将工作:
{
"id":1,
"bar":"string"
}
and this will (rightfully ) return Key: 'Foo.ID' Error:Field validation for 'ID' failed on the 'required' tag
这将(正确地)返回
Key: 'Foo.ID' Error:Field validation for 'ID' failed on the 'required' tag
{ "bar":"string" } {“ bar”:“ string”}
var (
msg string
)
switch errs.(type) {
case *json.UnmarshalTypeError:
msg = errs.(*json.UnmarshalTypeError).Field + " type error."
case validator.ValidationErrors:
validationErrs := errs.(validator.ValidationErrors)
for _, e := range validationErrs.Translate(trans) {
msg = e
break
}
default:
msg = "unknow error"
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.