【Gin】Gin JSON渲染,获取参数,参数绑定

  • 1.JSON渲染
  • 2.获取querystring参数
  • 3.获取form参数
  • 4.path参数获取
  • 5.获取JSON参数
  • 6.参数绑定
  • 初步使用结构体
  • .ShouldBind()参数绑定


1.JSON渲染

package main

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

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

	r.GET("/json", func(c *gin.Context) {
		// 方法:使用map序列化json数据
		data := map[string]interface{}{
			"name":    "dahe",
			"message": "json method",
			"age":     18,
		}
		// 返回状态码和json数据
		c.JSON(http.StatusOK, data)
	})

	r.Run(":9090") // 启动server
}

访问json地址,获取数据:

android Gson 获取JSON对象 gin获取json数据_restful

更简单的方法:使用gin.H

gin.Hmap[string]interface{}的缩写👝

package main

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

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

	r.GET("/json", func(c *gin.Context) {
		// 方法:使用gin.H
		data := gin.H{
			"name": "wangwei",
			"age":  18,
		}
		// 返回状态码和json数据
		c.JSON(http.StatusOK, data)
	})

	r.Run(":9090") // 启动server
}

Gin很灵活,我们还可以使用结构体:

package main

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

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

	type msg struct {
		Name    string
		Message string
		Age     int
	}

	r.GET("/json", func(c *gin.Context) {
		// 方法:使用结构体
		data := msg{
			"dahe",
			"你好世界!",
			22,
		}

		// 返回状态码和json数据
		c.JSON(http.StatusOK, data)
	})

	r.Run(":9090") // 启动server
}

附:灵活使用tag来自定义json数据属性名:🛍️

type msg struct {
	Name    string `json:"name"`
	Message string
	Age     int
}

2.获取querystring参数

querystring指的是URL中?后面携带的参数,例如:/user/search?username=文杰&address=china。 获取请求的querystring参数的方法如下:

package main

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

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

	r.GET("/query", func(c *gin.Context) {
		// 获取浏览器的发出请求携带的 query string 参数
		name := c.Query("name")
		c.JSON(http.StatusOK, gin.H{
			"name": name,
		})
	})

	r.Run(":9090") // 启动server
}

访问:http://127.0.0.1:9090/query?name=dahe
输出:{“name”:“dahe”}

设置没有接受搜索内容的默认参数值:

name := c.DefaultQuery("name", "无名氏")
// 如果没有传入参数,默认接受值:无名氏

访问:http://127.0.0.1:9090/query
输出:{“name”:“无名氏”}

带bool值的接受:

name, ok := c.GetQuery("name")
if !ok {
	// 没有传值,则设置默认的值
	name = "无名氏"
}

接受多个值的情况:

r.GET("/query", func(c *gin.Context) {
	// 获取浏览器的发出请求携带的 query string 参数
	name := c.Query("name")
	age := c.Query("age")
	c.JSON(http.StatusOK, gin.H{
		"name": name,
		"age":  age,
	})
})

访问:http://127.0.0.1:9090/query?name=dahe&age=18
输出:{“age”:“18”,“name”:“dahe”}


3.获取form参数

login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<form action="/login/" method="post">
    账号:
    <input type="text" name="username" id="username">
    密码:
    <input type="password" name="password" id="password">
    <input type="submit" value="登录">
</form>
</body>
</html>

后端接受接口:

package main

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

func main() {
	r := gin.Default()
	r.LoadHTMLFiles("./login.html")
	// 登录模块
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.html", nil)
	})

	// 接受form表单数据
	r.POST("/login", func(c *gin.Context) {
		// 获取form表单数据
		username := c.PostForm("username")
		password := c.PostForm("password")
		c.JSON(http.StatusOK, gin.H{
			"Name":     username,
			"Password": password,
		})
	})

	r.Run(":9090") // 启动server
}

也可以使用DefaultPostForm来接受值:

package main

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

func main() {
	r := gin.Default()
	r.LoadHTMLFiles("./login.html")
	// 登录模块
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.html", nil)
	})

	// 接受form表单数据
	r.POST("/login", func(c *gin.Context) {
		// 获取form表单数据
		username := c.DefaultPostForm("username", "李华")
		password := c.DefaultPostForm("password", "admin")
		msg := c.DefaultPostForm("msg", "晚上好!")
		c.JSON(http.StatusOK, gin.H{
			"Name":     username,
			"Password": password,
			"msg":      msg,
		})
	})

	r.Run(":9090") // 启动server
}

由于form表单没有msg字段,所以msg采用默认的值

输出:{"Name":"admin","Password":"111111","msg":"晚上好!"}


4.path参数获取

请求的参数通过URL路径传递,例如:/user/search/dahe/用户1359。 获取请求URL路径中的参数的方式如下:

package main

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

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

	r.GET("/:name/:age", func(c *gin.Context) {
		name := c.Param("name")
		age := c.Param("age")
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})

	r.Run(":9090") // 启动server
}

访问路径:http://localhost:9090/dahe/18
输出:{“age”:“18”,“name”:“dahe”}


5.获取JSON参数

当前端请求的数据通过JSON提交时,例如向/json发送一个POST请求,则获取请求参数的方式如下:

r.POST("/json", func(c *gin.Context) {
	// 注意:下面为了举例子方便,暂时忽略了错误处理
	b, _ := c.GetRawData()  // 从c.Request.Body读取请求数据
	// 定义map或结构体
	var m map[string]interface{}
	// 反序列化
	_ = json.Unmarshal(b, &m)

	c.JSON(http.StatusOK, m)
})

6.参数绑定

为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryStringform表单JSONXML等参数到结构体中

初步使用结构体

package main

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

// 用户结构体
type UserInfo struct {
	username string
	password string
}

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

	r.GET("/", func(c *gin.Context) {
		username := c.Query("username")
		password := c.Query("password")
		u := UserInfo{
			username: username,
			password: password,
		}
		fmt.Printf("%#v\n", u)
		c.JSON(http.StatusOK, gin.H{
			"message": "ok",
		})
	})

	r.Run(":9090") // 启动server
}

访问:http://localhost:9090/?username=dahe&password=123
控制台输出:main.UserInfo{username:“dahe”, password:“123”}

.ShouldBind()参数绑定

.ShouldBind()强大的功能,它能够基于请求自动提取JSONform表单QueryString类型的数据,并把值绑定到指定的结构体对象

package main

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

// 用户结构体
type UserInfo struct {
	Username string `form:"username" json:"username"`
	Password string `form:"password" json:"password"`
}

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

	r.GET("/user", func(c *gin.Context) {
		var u UserInfo // 声明一个UserInfo类型的变量u
		err := c.ShouldBind(&u)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
		} else {
			fmt.Printf("%#v\n", u)
			c.JSON(http.StatusOK, gin.H{
				"message": "ok",
			})
		}
	})

	r.Run(":9090") // 启动server
}

访问:http://localhost:9090/user?username=dahe&password=admin
控制台输出:main.UserInfo{Username:“dahe”, Password:“admin”}

ShouldBind会按照下面的顺序解析请求中的数据完成绑定:

  • 如果是 GET 请求,只使用 Form 绑定引擎(query)。
  • 如果是 POST 请求,首先检查 content-type 是否为 JSONXML,然后再使用 Form(form-data)。

更完善的实例:

// Binding from JSON
type Login struct {
	User     string `form:"user" json:"user" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

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

	// 绑定JSON的示例 ({"user": "q1mi", "password": "123456"})
	router.POST("/loginJSON", func(c *gin.Context) {
		var login Login

		if err := c.ShouldBind(&login); err == nil {
			fmt.Printf("login info:%#v\n", login)
			c.JSON(http.StatusOK, gin.H{
				"user":     login.User,
				"password": login.Password,
			})
		} else {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
	})

	// 绑定form表单示例 (user=q1mi&password=123456)
	router.POST("/loginForm", func(c *gin.Context) {
		var login Login
		// ShouldBind()会根据请求的Content-Type自行选择绑定器
		if err := c.ShouldBind(&login); err == nil {
			c.JSON(http.StatusOK, gin.H{
				"user":     login.User,
				"password": login.Password,
			})
		} else {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
	})

	// 绑定QueryString示例 (/loginQuery?user=q1mi&password=123456)
	router.GET("/loginForm", func(c *gin.Context) {
		var login Login
		// ShouldBind()会根据请求的Content-Type自行选择绑定器
		if err := c.ShouldBind(&login); err == nil {
			c.JSON(http.StatusOK, gin.H{
				"user":     login.User,
				"password": login.Password,
			})
		} else {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
	})

	// Listen and serve on 0.0.0.0:8080
	router.Run(":8080")
}