JSON 是 API 最常用的数据格式。Gin 提供了便捷的 JSON 绑定功能。
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
r.POST("/users", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, user)
})
请求:
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"alice@example.com"}'
结构体标签控制 JSON 字段映射:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"-"` // 忽略此字段
Age int `json:"age,omitempty"` // 为空时忽略
CreatedAt string `json:"created_at"` // 重命名字段
}
| 选项 | 说明 |
|---|---|
json:"name" | 字段名映射 |
json:"-" | 忽略字段 |
json:",omitempty" | 零值时不输出 |
json:"name,omitempty" | 组合使用 |
type Address struct {
City string `json:"city"`
Country string `json:"country"`
}
type User struct {
Name string `json:"name"`
Address Address `json:"address"`
}
r.POST("/users", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, user)
})
请求:
{
"name": "Alice",
"address": {
"city": "Beijing",
"country": "China"
}
}
type CreateOrderRequest struct {
UserID string `json:"user_id"`
Items []string `json:"items"`
}
r.POST("/orders", func(c *gin.Context) {
var req CreateOrderRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{
"user_id": req.UserID,
"items": req.Items,
})
})
请求:
{
"user_id": "123",
"items": ["item1", "item2", "item3"]
}
r.POST("/config", func(c *gin.Context) {
var config map[string]interface{}
if err := c.ShouldBindJSON(&config); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, config)
})
指针字段可以区分空值和未提供:
type User struct {
Name string `json:"name"`
Email *string `json:"email"` // nil 表示未提供
}
r.PATCH("/users/:id", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if user.Email != nil {
// 更新 email
}
c.JSON(200, user)
})
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Address struct {
City string `json:"city"`
Street string `json:"street"`
Country string `json:"country"`
}
type User struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"gte=0,lte=150"`
Tags []string `json:"tags"`
Address Address `json:"address"`
Active *bool `json:"active"`
}
func main() {
r := gin.Default()
r.POST("/users", createUser)
r.PATCH("/users/:id", updateUser)
r.Run(":8080")
}
func createUser(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{
"message": "用户创建成功",
"user": user,
})
}
func updateUser(c *gin.Context) {
id := c.Param("id")
var updates map[string]interface{}
if err := c.ShouldBindJSON(&updates); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"id": id,
"updates": updates,
})
}
这一章学习了: