validator icon indicating copy to clipboard operation
validator copied to clipboard

Validate type shopspring/decimal multi value

Open tawoli opened this issue 6 years ago • 2 comments

Package version eg. v8, v9:

v9

Issue, Question or Enhancement:

I'm using shopspring/decimal for decimal type. Is there a way for me to validate multiple field in Decimal? eg:(neg、abs) in decimal.Decimal.value, exp in decimal.Decimal neg represents positive and negative abs stands for all numbers exp is the decimal point I know RegisterCustomTypeFunc() can be use to validate a field,but how to validate multiple filed? English is poor, forgive me.

Code sample, to showcase or reproduce:

type ProductInfo struct {
	gorm.Model
	Title       *string          `gorm:"not null" validate:"required"`
	Price       *decimal.Decimal `gorm:"not null;type:decimal(10,2)" validate:"required,gte=0,dive"`
	Description *string          `gorm:"not null;default:'';size:500" validate:"required"`
	Sales       *uint            `gorm:"not null;default:0"`
	ImgURL      *string          `gorm:"not null;default:''" validate:"required"`
}

// this is decimal.Decimal
type Decimal struct {
	value *big.Int
	exp int32
}

// big.Int
package big
type Int struct {
	neg bool // sign
	abs nat  // absolute value of the integer
}

tawoli avatar Sep 17 '19 09:09 tawoli

Try RegisterCustomTypeFunc, example - https://github.com/go-playground/validator/issues/470#issuecomment-607876264

vtopc avatar Aug 05 '21 14:08 vtopc

try this example

package main

import (
	"log"
	"reflect"

	"github.com/go-playground/validator/v10"
	"github.com/shopspring/decimal"
)

// use a single instance of Validate, it caches struct info
var validate *validator.Validate

type Item struct {
	Price decimal.Decimal `validate:"dgt=10"`
}

func main() {
	validate = validator.New()
	decimalGreaterThan()
	pirce, _ := decimal.NewFromString("1")
	u := Item{
		Price: pirce,
	}
	err := validate.Struct(u)
	log.Println(err)
}

func decimalGreaterThan() error {
	validate.RegisterCustomTypeFunc(func(field reflect.Value) interface{} {
		if valuer, ok := field.Interface().(decimal.Decimal); ok {
			return valuer.String()
		}
		return nil
	}, decimal.Decimal{})
	if err := validate.RegisterValidation("dgt", func(fl validator.FieldLevel) bool {
		data, ok := fl.Field().Interface().(string)
		if !ok {
			return false
		}
		value, err := decimal.NewFromString(data)
		if err != nil {
			return false
		}
		baseValue, err := decimal.NewFromString(fl.Param())
		if err != nil {
			return false
		}
		return value.GreaterThan(baseValue)
	}); err != nil {
		return err
	}

	return nil
}

wychl avatar Sep 02 '22 07:09 wychl