golangWeb框架---github.com/gin-gonic/gin學習四(模型綁定、自定義校驗、ShouldBindXXX、BindXXX)


文章目錄
模型綁定、校驗
綁定json(ShouldBindJSON)
綁定xml(ShouldBindXML)、form(ShouldBind)
自定義校驗器(demo有問題)
BindQuery\ShouldBindQuery(只限查詢參數)
BindJson(json)、Bind(查詢參數、formdata)
模型綁定、校驗
以下來自百度翻譯:

若要將請求體綁定到類型,請使用模型綁定。我們目前支持JSON、XML和標准表單值的綁定(Foo= Bar和Bo.BAZ)。

GIN使用Go PooWorks/Valual.V8進行驗證。在這里查看標簽使用的完整文檔。

注意,需要在所有要綁定的字段上設置相應的綁定標記。例如,當從JSON綁定時,設置JSON:“FieldNeX”。

類型——必須綁定
Methods-Bind, BindJSON, BindXML, BindQuery
Behavior-These methods use MustBindWith under the hood。如果綁定錯誤,請求將被 c.AbortWithError(400, err).SetType(ErrorTypeBind) 中止,響應狀態碼將被設置成400,響應頭 Content-Type 將被設置成 text/plain;charset=utf-8。如果你嘗試在這之后設置相應狀態碼,將產生一個頭已被設置的警告。如果想更靈活點,則需要使用 ShouldBind 類型的方法。

類型——應該綁定
Methods-ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery
Behavior-These methods use ShouldBindWith under the hood。如果出現綁定錯誤,這個錯誤將被返回,並且開發人員可以進行適當的請求和錯誤處理

當使用綁定方法時,GIN嘗試根據內容類型頭推斷綁定器。如果你確信你有什么約束力,你可以使用MubBin或SubBudIdIn。
還可以指定需要特定的字段。如果字段裝訂為綁定:“必需”,並且綁定時具有空值,則會返回錯誤

我們通過一個實際例子來看下,代碼都很簡單,我就直接貼出來了

綁定json(ShouldBindJSON)
package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

 

func main() {
router := gin.Default()

router.POST("/loginJSON", func(c *gin.Context) {
var json Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Login information is not complete"})
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"})
})

router.Run(":8080")
}

type Login struct {
User string `form:"user" json:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" xml:"password" binding:"required"`
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
簡單說下,Login結構體,通過binding:"required"進行了必須綁定,就是請求時候,必須帶上該參數,還分別進行了form、json、xml類型,這里我們先嘗試下json 類型
我們同樣是執行幾條指令來看看返回都結果提示:

當執行"user":"manu",只有一個user參數時候,

$ curl -X POST http://localhost:8080/loginJSON
-H 'content-type:application/json' -d '{"user":"manu"}'
1
2
輸出結果如下:

{"error":"Login information is not complete"}
1

當執行`"user":"manu","password":"123d"`,2個參數時候,但是密碼不正確的前提下
$ curl -X POST http://localhost:8080/loginJSON
-H 'content-type:application/json' -d '{"user":"manu","password":"123d"}'
1
2
輸出結果如下:

{"status":"unauthorized"}
1

當執行`"user":"manu","password":"123d"`,2個參數時候,但是密碼不正確的前提下
$ curl -X POST http://localhost:8080/loginJSON
-H 'content-type:application/json' -d '{"user":"manu","password":"123"}'
1
2
輸出結果如下:

{"status":"you are logged in"}
1
綁定xml(ShouldBindXML)、form(ShouldBind)
以下就是綁定xml、form類型的,我只貼出代碼即可,用法是一樣的

綁定xml
1

// Example for binding XML (
// <?xml version="1.0" encoding="UTF-8"?>
// <root>
// <user>user</user>
// <password>123</user>
// </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"})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
綁定form
1
// 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"})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
自定義校驗器(demo有問題)
我們可以注冊自定義驗證器
Validator docs -
https://godoc.org/gopkg.in/go-playground/validator.v8#Validate.RegisterStructValidation

Struct level example -
https://github.com/go-playground/validator/blob/v8.18.2/examples/struct-level/struct_level.go

Validator release notes -
https://github.com/go-playground/validator/releases/tag/v8.7

可以參考如上的連接,接下來我把gin框架官網的樣例拿出來

package main

import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"gopkg.in/go-playground/validator.v8"
"net/http"
"reflect"
"time"
)

type Booking struct {
CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
CheckOut time.Time `form:"check_out" binding:"required,bookabledate" time_format:"2006-01-02"`
}

 

func bookableDate(
v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
) bool {
if date, ok := field.Interface().(time.Time); ok {
today := time.Now()

if today.Year() > date.Year() || today.YearDay() > date.YearDay() {
return false
}
}
return true
}

 


func main() {
route := gin.Default()

if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("bookabledate", bookableDate)
}

route.GET("/bookable", getBookable)
route.Run(":8080")
}

func getBookable(c *gin.Context) {
var b Booking
if err := c.ShouldBindWith(&b, binding.Query); err == nil {
c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
執行命令

zhiliaodeMBP:go zhiliao$ curl -X GET http://localhost:8080/bookable?check_in=2018-09-20&check_out=2018-09-21
[1] 69601
zhiliaodeMBP:go zhiliao$ {"error":"Key: 'Booking.CheckOut' Error:Field validation for 'CheckOut' failed on the 'required' tag"}
[1]+ Done curl -X GET http://localhost:8080/bookable?check_in=2018-09-20
zhiliaodeMBP:go zhiliao$

1
2
3
4
5
6
不知道為何我這里會報錯
先跳過,有知道到給我留言,多謝~~

BindQuery\ShouldBindQuery(只限查詢參數)
BindQuery\ShouldBindQuery函數只綁定查詢參數,而不綁定POST數據。

我現在只BindQuery來試驗,ShouldBindQuery我測試輸出結果一樣

package main

import "log"
import "github.com/gin-gonic/gin"

type Person struct {
Name string `form:"name"`
Address string `form:"address"`
}

func main() {
route := gin.Default()
route.Any("/testing", startPage)
route.Run(":8080")
}
func startPage(c *gin.Context) {
var person Person
if c.BindQuery(&person) == nil {
log.Println("====== Only Bind Query String ======")
log.Println(person.Name)
log.Println(person.Address)
}
c.String(200, "Success")
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
通過執行curl -X GET "localhost:8080/testing?name=eason&address=xyz"
最后log輸出日志如下:


BindJson(json)、Bind(查詢參數、formdata)
Bind:only bind the query or post data!!!

BindJson:only bind the json data!!!

package main

import "log"
import "github.com/gin-gonic/gin"

type Person struct {
Name string `form:"name" json:"name"`
Address string `form:"address" json:"address"`
}

func main() {
route := gin.Default()
route.Any("/testing", startPage)
route.Run(":8080")
}
func startPage(c *gin.Context) {
var person Person

if c.Bind(&person) == nil {
log.Println("====== Bind By Query String ======")
log.Println(person.Name)
log.Println(person.Address)
}

if c.BindJSON(&person) == nil {
log.Println("====== Bind By JSON ======")
log.Println(person.Name)
log.Println(person.Address)
}


c.String(200, "Success")
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
測試如下:
1、輸入指令測試Bind,參數
curl -X GET "localhost:8080/testing?name=appleboy&address=xyz"
輸出結果如下:

2018/09/20 17:35:19 ====== Bind By Query String ======
2018/09/20 17:35:19 appleboy
2018/09/20 17:35:19 xyz
1
2
3
2、輸入指令測試Bind,用來測試formdata,這里我用了postman

3、輸入指令來測試BindJSON

zhiliaodeMBP:go zhiliao$ curl -X GET localhost:8080/testing --data '{"name":"JJ", "address":"xyz"}' -H "Content-Type:application/json"
1
輸出結果如下:

2018/09/20 17:31:46 ====== Bind By JSON ======
2018/09/20 17:31:46 JJ
2018/09/20 17:31:46 xyz
————————————————
版權聲明:本文為CSDN博主「丙申」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u013210620/java/article/details/82787010


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM