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

  • 相关阅读:
    ListNode Java创建链表
    Remove Nth Node From End of List LeetCode Java
    Rotate List LeetCode Java
    LeetCode刷题感想
    Swap Nodes in Pairs LeetCode Java
    Reverse Nodes in k-Group LeetCode Java
    334. Increasing Triplet Subsequence
    300. Longest Increasing Subsequence
    130. Surrounded Regions
    200. Number of Islands
  • 原文地址:https://www.cnblogs.com/ExMan/p/12960841.html
Copyright © 2011-2022 走看看