Go Gin:创建通用的自定义验证器

huangapple go评论101阅读模式
英文:

Go Gin : Creating generic custom validators

问题

我正在使用Go Gin在我的项目中创建API。我有一个要求,需要创建自定义验证器,所以我创建了以下代码:

var valueone validator.Func = func(fl validator.FieldLevel) bool {
	value, ok := fl.Field()
	if ok {
		if value != "one" {
                  return true
                }
	}
	return true
}

var valuetwo validator.Func = func(fl validator.FieldLevel) bool {
	value, ok := fl.Field()
	if ok {
		if value != "two" {
                  return true
                }
	}
	return true
}
....

我想知道是否有一种方法可以创建一个更通用的单个验证器,可以用于这两种情况,类似于:

var value validator.Func = func(fl validator.FieldLevel, param) bool {
	value, ok := fl.Field()
	if ok {
		if value != param {
                  return true
                }
	}
	return true
}

我无法找到在Gin中传递参数给自定义验证器的方法,也无法通过其他方式创建这些通用验证器。我需要创建成千上万个几乎相似的验证器,而我不想为每个验证器都创建自定义验证器。

英文:

I am using go Gin to create APIs in my project. I have requirement to create custom validators so I created like:

var valueone validator.Func = func(fl validator.FieldLevel) bool {
	value, ok := fl.Field()
	if ok {
		if value != "one" {
                  return true
                }
	}
	return true
}

var valuetwo validator.Func = func(fl validator.FieldLevel) bool {
	value, ok := fl.Field()
	if ok {
		if value != "two" {
                  return true
                }
	}
	return true
}
....

Instead of creating almost same custom validator multiple times, is there a way to create a single validator which is more generic and can be used for both cases, something like:

var value validator.Func = func(fl validator.FieldLevel, param) bool {
	value, ok := fl.Field()
	if ok {
		if value != param {
                  return true
                }
	}
	return true
}

I am not able to find a way to pass parameter to custom validator in gin or to make these generic validators through any other possible way. I have requirement to create like thousands of almost similar validator and I don't want to create custom validator for each one of them.

答案1

得分: 2

你不能更改函数结构,因为它是在包中定义的。

// Func接受FieldLevel接口以满足所有验证需求。当验证成功时,返回值应为true。

type Func func(fl FieldLevel) bool

相反,我们可以尝试使用带有参数的自定义验证标签。

请参考下面的示例:

package main

import (
	"github.com/go-playground/validator"
)

type Data struct {
	One string `json:"one" validate:"custom_validation=one"`
	Two string `json:"two" validate:"custom_validation=two"`
}

var validate *validator.Validate

func main() {
	validate = validator.New()

	err := validate.RegisterValidation("custom_validation", func(fl validator.FieldLevel) bool {
		value := fl.Field()
		param := fl.Param()

		return value.String() == param
	})

	if err != nil {
		panic(err)
	}

	// 这将成功
	{
		data := &Data{
			One: "one",
			Two: "two",
		}

		err = validate.Struct(data)
		if err != nil {
			panic(err)
		}
	}

	// 这里将失败
	{
		data := &Data{
			Two: "one",
			One: "two",
		}

		err = validate.Struct(data)
		if err != nil {
			panic(err)
		}
	}
}

这里可以找到更多示例。

注意:Golang不支持!==

英文:

You can't change the function structure, as this is how it defined within the package.

// Func accepts a FieldLevel interface for all validation needs. The return
// value should be true when validation succeeds.

type Func func(fl FieldLevel) bool

instead, we could try custom validation tag with a parameter

see the sample below

package main

import (
	"github.com/go-playground/validator"
)

type Data struct {
	One string `json:"one" validate:"custom_validation=one"`
	Two string `json:"two" validate:"custom_validation=two"`
}

var validate *validator.Validate

func main() {
	validate = validator.New()

	err := validate.RegisterValidation("custom_validation", func(fl validator.FieldLevel) bool {
		value := fl.Field()
		param := fl.Param()

		return value.String() == param
	})

	if err != nil {
		panic(err)
	}

	// this will succeed
	{
		data := &Data{
			One: "one",
			Two: "two",
		}

		err = validate.Struct(data)
		if err != nil {
			panic(err)
		}
	}

	// it will fail here
	{
		data := &Data{
			Two: "one",
			One: "two",
		}

		err = validate.Struct(data)
		if err != nil {
			panic(err)
		}
	}
}

See more examples at here

Note : Golang doesn't support !==

答案2

得分: 2

在go-playground/validator中,Gin用于验证的库,你可以定义自定义验证器并使用参数,然后将参数包含在结构体的验证标签中。

以下是如何实现的步骤:

首先,注册一个带有标签名equals的函数。函数的第二个参数是标签的参数,它将是你想要检查是否相等的值:

validate := validator.New()
_ = validate.RegisterValidation("equals", func(fl validator.FieldLevel) bool {
    param := fl.Param()
    return fl.Field().String() == param
})

然后,在你的结构体中,你可以使用equals标签,后面跟着**=**和值:

type MyStruct struct {
    FieldOne string `validate:"equals=one"`
    FieldTwo string `validate:"equals=two"`
}

在这种情况下,FieldOne必须等于"one",而FieldTwo必须等于"two"。

因此,通过这种方法,你只需要定义一次自定义验证函数,然后可以在不同的字段上重复使用它,使用不同的参数。

请注意,**fl.Param()将参数作为字符串返回。如果你的参数不是字符串,你可能需要在验证函数内部将它们解析为实际的类型。此外,确保对validator.New()validate.RegisterValidation()**可能返回错误的情况进行错误处理。

英文:

In go-playground/validator, which Gin uses for validation, you can define your custom validator to use a parameter, and you can include the parameter in the validation tag in your struct.

Here's how you can do it:

First, register a function with the tag name equals. The second parameter in the function is the tag's parameter, which will be the value you want to check for equality against:

validate := validator.New()
_ = validate.RegisterValidation("equals", func(fl validator.FieldLevel) bool {
    param := fl.Param()
    return fl.Field().String() == param
})

Then, in your struct, you can use the equals tag followed by = and the value:

type MyStruct struct {
    FieldOne string `validate:"equals=one"`
    FieldTwo string `validate:"equals=two"`
}

In this case, FieldOne must equal "one" and FieldTwo must equal "two".

So, with this approach, you only have to define your custom validation function once, and then you can reuse it with different parameters for different fields.

Please note that fl.Param() returns the parameter as a string. If your parameters are not strings, you might need to parse them to their actual type inside the validation function. Also, ensure to do error handling for cases when validator.New() and validate.RegisterValidation() might return an error.

huangapple
  • 本文由 发表于 2023年6月27日 14:00:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76561991.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定