Gin JSON渲染,获取参数,参数绑定大全
获取Query参数
Query参数又叫Querystring参数,是URL的?后面的一串字符串。
demo代码如下:
r.GET("/home", func(c *gin.Context) { username := c.Query("username") password := c.DefaultQuery("password", "******") addr := c.QueryArray("addr") class := c.QueryMap("class") age, ok := c.GetQuery("age") if ok != true { fmt.Println(ok) } c.JSON(http.StatusOK, gin.H{ "username": username, "password": password, "addr": addr, "class": class, "age": age, }) })
结果如下:
总结:
Query()用来获取参数
使用DefaultQuery()方法时,如果没有相应的参数,就会使用defaultValue的值来代替。
QueryArray()和QueryMap()方法分别获取切片类型和字典类型的参数
GetQuery()方法返回两个值,一个value,一个bool值。当能够获取到相应的值时,bool值=true;当不能够获取到相应的值时,value为空,bool值=false。
需要注意的是切片类型的参数和字典类型的参数的写法。
切片:addr=aaa&addr=bbb
字典:class[专业]=软件工程&class[年级]=大一
获取Path参数
Path参数就是路径参数,也就是URL中斜杠和斜杠之间的参数
demo代码如下:
r.GET("/user/info/:username/:password/:hobby", func(c *gin.Context) { username := c.Param("username") password := c.Param("password") hobby := c.Param("hobby") params := c.Params c.JSON(http.StatusOK, gin.H{ "username": username, "password": password, "hobby": hobby, "params": params, }) })
结果如下:
总结:
把获取的Path参数的前面加上“ : ”,就表示这个Path参数是要获取的参数。
Param()方法只能一个一个的获取参数。
Params()方法是一次性获取所有的Path参数,返回的是Params类型,该类型的定义如下
type Param struct { Key string Value string } type Params []Param
当有一部分Path参数获取不到时,前面获取到的Path参数都会全部丢弃。其本质原因是底层使用rang遍历所有的Path参数,如果没有相应的参数,会把整个params切片置为空。源码如下:
func (ps Params) Get(name string) (string, bool) { for _, entry := range ps { if entry.Key == name { return entry.Value, true } } return "", false //注意:并不是将entry.Value置为nil,而是将整个切片置为空。 } func (ps Params) ByName(name string) (va string) { va, _ = ps.Get(name) return } func (c *Context) Param(key string) string { return c.Params.ByName(key) }
获取Form表单参数
Demo代码如下:
r.POST("/info", func(c *gin.Context) { username := c.PostForm("username") password := c.DefaultPostForm("password", "******") hobby := c.PostFormArray("hobby") sex, ok := c.GetPostForm("sex") if ok != true { fmt.Println(ok) } c.JSON(http.StatusOK, gin.H{ "username": username, "password": password, "sex": sex, "hobby": hobby, }) })
结果如下:
总结:
PostForm()方法获取表单参数
使用DefaultPostForm()方法如果没有获取到参数,会有默认值代替
PostFormArray()获取数组对象的表单参数
GetPostForm()方法返回两个值,第一个是表单参数,第二个是bool值
获取Json参数
Demo代码如下:
r.POST("/json", func(c *gin.Context) { var m map[string]interface{} body, err := c.GetRawData() //从请求体(body)中获取json数据 if err != nil { fmt.Println(err.Error()) } err = json.Unmarshal(body, &m) if err != nil { fmt.Println(err.Error()) } name := m["name"] email := m["email"] c.JSON(http.StatusOK, gin.H{ "name": name, "email": email, }) })
结果如下:
总结:
GetRawData()方法是从请求体(body)中获取原始的json数据
GetRawData()底层使用ioutil包里面的ReadAll()方法来读取数据,ReadAll()方法底层使用io包里面的ReadAll()函数,ReadAll()函数的源码如下:
func ReadAll(r Reader) ([]byte, error) { b := make([]byte, 0, 512) for { if len(b) == cap(b) { // Add more capacity (let append pick how much). b = append(b, 0)[:len(b)] } n, err := r.Read(b[len(b):cap(b)]) b = b[:len(b)+n] if err != nil { if err == EOF { err = nil } return b, err } } }
源码分析可以看这篇文章:
io.ReadAll 怎样读全部
获取请求头中的数据
Demo代码如下:
r.GET("/header", func(c *gin.Context) { token := c.GetHeader("Authorization") c.JSON(http.StatusOK, gin.H{ "Authorization": token, }) })
结果如下:
总结:
GetHeader()方法用于获取请求头信息
设置请求头的方法有两种:
c.Header(“Authorization”, “xxx.yyy.zzz”) c.Writer.Header().Set(“Authorization”, “xxx.yyy.zzz”)
数据绑定
基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。 下面的示例代码演示了BindJSON()和ShouldBindJSON,它能够基于请求自动提取JSON类型的数据,并把值绑定到指定的结构体对象。
Demo代码如下:
type Login struct { Username string `json:"username"` Password string `json:"password"` } r.GET("/bindJson", func(c *gin.Context) { var login Login err := c.BindJSON(&login) if err != nil { fmt.Println(err.Error()) } username := login.Username password := login.Password c.JSON(http.StatusOK, Login{ Username: username, Password: password, }, ) }) r.GET("/shouldBindJson", func(c *gin.Context) { var login Login err := c.ShouldBindJSON(&login) if err != nil { fmt.Println(err.Error()) } username := login.Username password := login.Password c.JSON(http.StatusOK, Login{ Username: username, Password: password, }, ) })
结果如下:
总结:
数据绑定是利用结构体的反射机制来实现的,只要结构体里面有相应的Tag标签,就能实现对应数据类型的绑定。
ShouldBindxxx和Bindxxx区别:如果Bindxxx没有绑定到数据,会在Header中添加400的返回信息,而ShouldBindxxx不会。验证结果如下: