Thursday, 13 February 2025

Validation in Go Gin: Binding Request Data (JSON, Form, Query)

In Go Gin, data binding (extracting request data into a struct) and validation are handled using struct tags. Gin supports binding and validating data from JSON, forms, query parameters, etc.


🔹 1. Binding JSON Data

Gin provides methods to bind request data to structs:

  • c.ShouldBind() or c.ShouldBindJSON(): Returns an error if data is invalid.
  • c.MustBind() or c.MustBindJSON(): Automatically returns HTTP 400 if an error occurs.

Example with JSON request:

go
package main import ( "github.com/gin-gonic/gin" "net/http" ) type User struct { Name string `json:"name" binding:"required"` Email string `json:"email" binding:"required,email"` Age int `json:"age" binding:"gte=18,lte=60"` } func main() { r := gin.Default() r.POST("/register", func(c *gin.Context) { var user User // Bind JSON request and validate if err := c.ShouldBindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Register success!", "user": user}) }) r.Run(":8080") }

📌 Explanation:

  • binding:"required" → Field is mandatory.
  • binding:"email" → Must be a valid email.
  • binding:"gte=18,lte=60" → Age must be between 18 and 60.

🔹 2. Binding Form Data (x-www-form-urlencoded)

For form-data requests, use ShouldBind() or ShouldBindForm():

go
type LoginForm struct { Username string `form:"username" binding:"required"` Password string `form:"password" binding:"required,min=6"` } r.POST("/login", func(c *gin.Context) { var form LoginForm if err := c.ShouldBind(&form); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Login success!", "user": form}) })

📌 Notes:

  • form:"username" → Extracts data from form fields.
  • binding:"min=6" → Password must have at least 6 characters.

🔹 3. Binding Query Parameters

If data comes from query parameters, use ShouldBindQuery():

go
type QueryParams struct { Page int `form:"page" binding:"required,gte=1"` Limit int `form:"limit" binding:"required,gte=5,lte=50"` } r.GET("/search", func(c *gin.Context) { var query QueryParams if err := c.ShouldBindQuery(&query); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"page": query.Page, "limit": query.Limit}) })

📌 Query Example:
GET /search?page=1&limit=10


🔹 4. Custom Validation

For custom validation rules, use validator.v10:

go
import ( "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "net/http" ) type User struct { Username string `json:"username" binding:"required,alphanum"` Age int `json:"age" binding:"checkAge"` } // Custom rule: age must be 18+ var validate *validator.Validate func checkAge(fl validator.FieldLevel) bool { return fl.Field().Int() >= 18 } func main() { r := gin.Default() validate = validator.New() validate.RegisterValidation("checkAge", checkAge) r.POST("/custom", func(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.StatusOK, gin.H{"message": "User valid!", "user": user}) }) r.Run(":8080") }

📌 Key Features:

  • RegisterValidation("checkAge", checkAge) → Registers custom validation.
  • binding:"alphanum" → Ensures the username contains only letters and numbers.
  • checkAge function → Prevents users under 18 years old.

🔹 Summary

MethodData Source
ShouldBindJSON(&obj)JSON body
ShouldBind(&obj)Auto-detects (JSON, form, query)
ShouldBindQuery(&obj)Query parameters
ShouldBindForm(&obj)Form-data

Using validation in Gin ensures data integrity, improves security, and simplifies API development! 🚀

No comments:

Post a Comment

Golang Advanced Interview Q&A