don't stop believing

Model binding and validation 본문

Golang/Gin

Model binding and validation

Tongchun 2019. 3. 6. 18:44

request로 전달되는 데이터를 지정된 type 또는 model에 바로 적용(bind)하는 기능입니다. 또한 넘어오는 데이터를 binding할때 필수 데이터가 있는지를 validation 할 수도 있습니다.

https://github.com/gin-gonic/gin#model-binding-and-validation


우선 bind type에는 크게 두가지가 있습니다. Must bindShould bind

Must bind의 Method는 Bind, BindJSON, BindXML, BindQuery, BindYAML 이렇게 있습니다.

Must bind는 request로 넘어온 데이터 중 bind할 대상이 없을 경우 바로 에러를 리턴합니다.

c.AbortWithError(400, err).SetType(ErrorTypeBind)


하지만 Should bind는 에러가 발생할 경우 개발자가 처리할 수 있습니다.

Should bind의 Method도 동일하게 ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML로 구성되어 있습니다.


binding을 사용하려면 먼저 struct를 만들어야 합니다.

저는 아래와 같이 만들었습니다.

type User struct {
	User     string `form:"user" json:"user" xml:"user"  binding:"required"`
	Password string `form:"password" json:"password" xml:"password"  binding:"required"`
	Nick     string `form:"nick" json:"nick" xml:"nick"`
	Age      uint16 `form:"age" json:"age" xml:"age"`
}

User struct안의 각 항목에 bind tag를 추가했습니다.

form post로 넘어왔을 경우와 body json으로 넘어 왔을때 그리고 xml 데이터로 왔을때 binding되는 key를 적어 줍니다.

그리고 binding: "required"일 경우 request되는 데이터에 반드시 넘어와야 되며 없을 경우 error가 리턴됩니다. 


이제 간단한 코드를 작성해 보겠습니다. (server.go)

package main import ( "net/http" "github.com/gin-gonic/gin" ) type User struct { User string `form:"user" json:"user" xml:"user" binding:"required"` Password string `form:"password" json:"password" xml:"password" binding:"required"` Nick string `form:"nick" json:"nick" xml:"nick"` Age uint16 `form:"age" json:"age" xml:"age"` } func setupRouter() *gin.Engine { // Disable Console Color // gin.DisableConsoleColor() r := gin.Default() r.POST("/binding/json", bindingTestJSON) r.POST("/binding/form", bindingTestFORM) return r } // bind from JSON func bindingTestJSON(c *gin.Context) { var json User if err := c.ShouldBindJSON(&json); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if json.User != "tongchun" || json.Password != "ngle1234" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return } c.JSON(http.StatusOK, gin.H{ "status": "you are logged in", "info": json, }) } // bind from FORM func bindingTestFORM(c *gin.Context) { var form User if err := c.ShouldBind(&form); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if form.User != "tongchun" || form.Password != "ngle1234" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return } c.JSON(http.StatusOK, gin.H{ "status": "you are logged in", "info": form, }) } func main() { r := setupRouter() // Listen and Server in 0.0.0.0:8080 r.Run(":8080") }

Post method로 json 데이터가 넘어오면 아래 binding 코드에서 json 데이터를 parsing해 각 항목에 binding하게 됩니다.

if err := c.ShouldBindJSON(&json); err != nil {

c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})

return

}

만약 tag에 정의한데로 필수 항목(binding: requested)이 없거나 빈 값으로 넘어오면 err 데이터를 반환합니다.

마찬가지로 form 데이터로 넘어온 데이터는 아래 binding 코드로 처리합니다.

if err := c.ShouldBind(&form); err != nil {

c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})

return

}

이제 server.go를 실행해 보겠습니다.

$ go run ./example/server.go 
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] POST   /binding/json             --> main.bindingTestJSON (3 handlers)
[GIN-debug] POST   /binding/form             --> main.bindingTestFORM (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080

postman으로 json 정상적인 데이터를 전송해 봅니다.

required 항목인 user에 공백을 값으로 넣어 보겠습니다.

required 항목의 값이 공백이거나 key 자체가 없다면 에러 메시지를 보냅니다.

post form 데이터도 동일합니다.


추가로 int 타입인 age에 binding 조건으로 13부터 33까지만 허용할 수 있습니다.

아래처럼 tag를 줄 수 있습니다.

type User struct {
	User     string `form:"user" json:"user" xml:"user"  binding:"required"`
	Password string `form:"password" json:"password" xml:"password"  binding:"required"`
	Nick     string `form:"nick" json:"nick" xml:"nick"`
	Age      uint16 `form:"age" json:"age" xml:"age" binding:"required,min=13,max=32"`
}

min값과 max값을 지정할 수 있고 이 범위를 벗어나면 아래와 같이 에러가 리턴됩니다.

여기까지 binding과 값에 대한 검증(validation)이었습니다.


'Golang > Gin' 카테고리의 다른 글

Only Bind Query String  (0) 2019.03.09
Bind Query String or Post Data  (0) 2019.03.09
mysql curd (with Gin)  (0) 2019.03.06
[swag] Gin에서 Swagger 사용하기  (0) 2019.03.04
Grouping routes  (0) 2019.03.04
Comments