Enlace y validación de modelos
Para enlazar el cuerpo de una solicitud a un tipo, usa el enlace de modelos. Actualmente soportamos el enlace de JSON, XML, YAML y valores de formulario estándar (foo=bar&boo=baz).
Gin usa go-playground/validator/v10 para la validación. Consulta la documentación completa sobre el uso de etiquetas aquí.
Ten en cuenta que necesitas establecer la etiqueta de enlace correspondiente en todos los campos que deseas enlazar. Por ejemplo, al enlazar desde JSON, establece json:"fieldname".
Además, Gin proporciona dos conjuntos de métodos para el enlace:
- Tipo - Enlace obligatorio
- Métodos -
Bind,BindJSON,BindXML,BindQuery,BindYAML - Comportamiento - Estos métodos usan
MustBindWithinternamente. Si hay un error de enlace, la solicitud se aborta conc.AbortWithError(400, err).SetType(ErrorTypeBind). Esto establece el código de estado de respuesta a 400 y el encabezadoContent-Typese establece atext/plain; charset=utf-8. Ten en cuenta que si intentas establecer el código de respuesta después de esto, resultará en una advertencia[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422. Si deseas tener mayor control sobre el comportamiento, considera usar el método equivalenteShouldBind.
- Métodos -
- Tipo - Enlace condicional
- Métodos -
ShouldBind,ShouldBindJSON,ShouldBindXML,ShouldBindQuery,ShouldBindYAML - Comportamiento - Estos métodos usan
ShouldBindWithinternamente. Si hay un error de enlace, el error se devuelve y es responsabilidad del desarrollador manejar la solicitud y el error apropiadamente.
- Métodos -
Al usar el método Bind, Gin intenta inferir el binder dependiendo del encabezado Content-Type. Si estás seguro de lo que estás enlazando, puedes usar MustBindWith o ShouldBindWith.
También puedes especificar que campos específicos son requeridos. Si un campo está decorado con binding:"required" y tiene un valor vacío al momento del enlace, se devolverá un error.
Si uno de los campos del struct es a su vez un struct (struct anidado), los campos de ese struct también necesitarán estar decorados con binding:"required" para validar correctamente.
// Binding from JSONtype Login struct { User string `form:"user" json:"user" xml:"user" binding:"required"` Password string `form:"password" json:"password" xml:"password" binding:"required"`}
func main() { router := gin.Default()
// Example for binding JSON ({"user": "manu", "password": "123"}) router.POST("/loginJSON", func(c *gin.Context) { var json Login if err := c.ShouldBindJSON(&json); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return }
if json.User != "manu" || json.Password != "123" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return }
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) })
// Example for binding XML ( // <?xml version="1.0" encoding="UTF-8"?> // <root> // <user>manu</user> // <password>123</password> // </root>) router.POST("/loginXML", func(c *gin.Context) { var xml Login if err := c.ShouldBindXML(&xml); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return }
if xml.User != "manu" || xml.Password != "123" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return }
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) })
// Example for binding a HTML form (user=manu&password=123) router.POST("/loginForm", func(c *gin.Context) { var form Login // This will infer what binder to use depending on the content-type header. if err := c.ShouldBind(&form); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return }
if form.User != "manu" || form.Password != "123" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return }
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) })
// Listen and serve on 0.0.0.0:8080 router.Run(":8080")}Solicitud de ejemplo
$ curl -v -X POST \ http://localhost:8080/loginJSON \ -H 'content-type: application/json' \ -d '{ "user": "manu" }'> POST /loginJSON HTTP/1.1> Host: localhost:8080> User-Agent: curl/7.51.0> Accept: */*> content-type: application/json> Content-Length: 18>* upload completely sent off: 18 out of 18 bytes< HTTP/1.1 400 Bad Request< Content-Type: application/json; charset=utf-8< Date: Fri, 04 Aug 2017 03:51:31 GMT< Content-Length: 100<{"error":"Key: 'Login.Password' Error:Field validation for 'Password' failed on the 'required' tag"}Omitir validación
Al ejecutar el ejemplo anterior usando el comando curl de arriba, devuelve un error. Porque el ejemplo usa binding:"required" para Password. Si usas binding:"-" para Password, entonces no devolverá error al ejecutar el ejemplo de nuevo.