I see that we can use c.bindJSON() to attach incoming request bodies to predefined structs. This method also validates the body in the process, which is great. I am wondering if I can have a standalone middleware that validates incoming request bodies using c.bindJSON() AND send the bound&verified body to the handler. This way I can write one single validate middleware for different requests with different structs.

Comment From: ljluestc

package main

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

// Define a struct to hold the data we expect in the request body
type MyRequest struct {
    Name  string `json:"name" binding:"required"`
    Email string `json:"email" binding:"required,email"`
}

// Custom middleware that binds and validates the JSON body
func BindAndValidateJSON() gin.HandlerFunc {
    return func(c *gin.Context) {
        var jsonBody MyRequest
        // Bind the incoming JSON request body to the struct
        if err := c.ShouldBindJSON(&jsonBody); err != nil {
            // If binding or validation fails, send a 400 response with the error
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            c.Abort()
            return
        }

        // If binding and validation succeed, store the result in the context
        c.Set("validatedBody", jsonBody)
        c.Next() // Continue to the next handler
    }
}

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

    // Apply the custom middleware on a route
    r.POST("/validate", BindAndValidateJSON(), func(c *gin.Context) {
        // Retrieve the validated body from the context
        validatedBody, exists := c.Get("validatedBody")
        if !exists {
            c.JSON(http.StatusInternalServerError, gin.H{"error": "No validated body"})
            return
        }

        // You can now use the validated body in your handler
        c.JSON(http.StatusOK, gin.H{
            "message": "Validation successful",
            "data":    validatedBody,
        })
    })

    // Run the server
    r.Run(":8080")
}