文章目录

模型绑定、校验

绑定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

————————————————