I have this struct for http request:

type jobPostRequest struct {
  Name string `json:"name"`
  Currency string `json:"currency"`
}

I would like to trim whitespaces in Name and capitalize currency, i.e. usd to USD. Just curious if anybody can recommend a non repetitive way to do this with gin. thanks

Comment From: PolarPanda611

define a customize type and implement the Unmarshal interface.

Comment From: jledesma84

@PolarPanda611 do you have any example of the implementation to be used in a POST method?

Comment From: jledesma84

@girafferiel you found the way to do it?

Comment From: victorybiz

Here is how I trimmed whitespace in the request body by integrating mold package with gin without rewriting/duplicating the entire binding package codes to create a custom binding for JSON and Form binding. I created a custom Validator to transform the data object before validating a struct and replacing the binding validator with my custom validator. Ensure to install the imported packages i.e mold and modifiers

Create the custom validator:

//  helpers/custom_validator_helper.go
package helpers

import (
    "context"
    "reflect"
    "github.com/go-playground/mold/v4/modifiers"
    "github.com/go-playground/validator/v10"
)

type CustomValidator struct {
    validator *validator.Validate
}

func NewCustomValidator() *CustomValidator {
    v := validator.New()
    // Set the tag name to "binding", SetTagName allows for changing of the default tag name of 'validate'
    v.SetTagName("binding")
    // Register Tag Name Function to get json name as alternate names for StructFields.
    v.RegisterTagNameFunc(func(fld reflect.StructField) string {
        return fld.Tag.Get("json")
    })
    // Register custom validation tags if needed
    v.RegisterValidation("customValidation", customValidationFunc)
    return &CustomValidator{validator: v}
}

// ValidateStruct is called by Gin to validate the struct
func (cv *CustomValidator) ValidateStruct(obj interface{}) error {
    // transform the object using mold before validating the struct
    transformer := modifiers.New()
    if err := transformer.Struct(context.Background(), obj); err != nil {
        return err
    }
    // validate the struct
    if err := cv.validator.Struct(obj); err != nil {
        return err
    }
    return nil
}

// Engine is called by Gin to retrieve the underlying validation engine
func (cv *CustomValidator) Engine() interface{} {
    return cv.validator
}

// Custom validation function
func customValidationFunc(fl validator.FieldLevel) bool {
    // Custom validation logic here
    return true
}

Call the custom validator and override the binding validator:

// main.go
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
)



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

    // Use custom validator
    customValidator := helpers.NewCustomValidator() // Create a new instance of your custom validator
    binding.Validator = customValidator             // Set the binding.Validator to your custom validator

    // Define your routes and handlers
    // ...

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

Then bind your Struct to the request using any of the default binding method

type Request struct {
    Email string `json:"email" mod:"trim" binding:"required,email"`
    Name string `json:"name" mod:"trim" binding:"required"`
}

func myHandler(c *gin.Context) {
    var req Request
    if err := c.ShouldBind(&req); err != nil {
        // Do smt...
    }
}

Comment From: KaymeKaydex

@appleboy , I suggest closing this issue, since this logic does not apply to gin