zoukankan      html  css  js  c++  java
  • golangWeb框架---github.com/gin-gonic/gin学习四(模型绑定、自定义校验、ShouldBindXXX、BindXXX)

    文章目录
    模型绑定、校验
    绑定json(ShouldBindJSON)
    绑定xml(ShouldBindXML)、form(ShouldBind)
    自定义校验器(demo有问题)
    BindQueryShouldBindQuery(只限查询参数)
    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
    不知道为何我这里会报错
    先跳过,有知道到给我留言,多谢~~

    BindQueryShouldBindQuery(只限查询参数)
    BindQueryShouldBindQuery函数只绑定查询参数,而不绑定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

  • 相关阅读:
    linux 命令——19 find (转)
    linux 命令——18 locate (转)
    linux 命令——17 whereis(转)
    linux 命令——16 which(转)
    linux 命令——15 tail (转)
    linux 命令——14 head (转)
    Java for LeetCode 038 Count and Say
    Java for LeetCode 037 Sudoku Solver
    Java for LeetCode 036 Valid Sudoku
    Java for LeetCode 035 Search Insert Position
  • 原文地址:https://www.cnblogs.com/ExMan/p/12960841.html
Copyright © 2011-2022 走看看