gin icon indicating copy to clipboard operation
gin copied to clipboard

Trimming whitespaces in request body

Open girafferiel opened this issue 2 years ago • 5 comments

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

girafferiel avatar Jun 29 '21 15:06 girafferiel

define a customize type and implement the Unmarshal interface.

PolarPanda611 avatar Jul 10 '21 15:07 PolarPanda611

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

jledesma84 avatar Jun 07 '23 18:06 jledesma84

@girafferiel you found the way to do it?

jledesma84 avatar Jun 07 '23 20:06 jledesma84

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...
	}
}

victorybiz avatar Jun 25 '23 17:06 victorybiz

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

KaymeKaydex avatar Apr 28 '24 18:04 KaymeKaydex