使用验证器来检查值是否为布尔值

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

Using validator to check if value is boolean

问题

我是新手,对Go不太熟悉,所以这可能很简单,但我找不到答案。我有一个名为Page的实体,有两个属性:

type Page struct {
    Title   string `form:"title" binding:"required"`
    Active  bool
}

现在,如果你不发送标题,我们会得到一个(不太好看,但可以接受的)错误信息:
Key: 'Page.Title' Error:Field validation for 'Title' failed on the 'required' tag

现在,如果我将以下内容发送到端点:

{
    "title": "我是一个有效的标题",
    "active": "我根本不是布尔值!"
}

我们会得到以下错误信息:
json: cannot unmarshal string into Go struct field Page.Active of type bool

在我看来,这提供了太多的信息。在Go中,验证用户输入的标准做法是什么?

我最初创建了一个page-validator.go文件进行一些检查,然后我找到了这个方法,但我不确定在Go中什么是最佳实践。
我应该如何正确验证这个输入?我应该检查提供的内容,然后尝试将其移入结构体并验证实际内容吗?

我正在使用GinGonic

  • 我找到了一种方法来解析错误并使其更友好。

英文:

I'm new to Go, so this might be very easy, but I can't find it. I have an entity Page with these two properties:

type Page struct {
	Title   string `form:"title" binding:"required"`
	Active  bool
}

Now, if you don't send a title we get a (not very pretty, but acceptable*):
Key: 'Page.Title' Error:Field validation for 'Title' failed on the 'required' tag.

Now, if I send this to the endpoint:

{
    "title": "I'm a valid title",
    "active": "I'm not a boolean at all!"
}

We get this:
json: cannot unmarshal string into Go struct field Page.Active of type bool

Which, IMO, is giving way too much info. What is the standard practice in Go to validate user input?

I was first making a page-validor.go with some checks, then I found this, but I'm not sure what is good practice in Go.
How do I validate this properly? Should I find check what is provided and then try to move it into the struct and validate the actual contents?

I am using GinGonic
* I've found a way to unwrap the errors and make it nicer

答案1

得分: 1

为类型Page编写自定义的JSON解组方法,并在UnmarshalJSON(bytes []byte)方法内部,将JSON字节解组为map[string]interface{},然后使用JSON字段键验证所需的类型。

JSON解组器的示例如下所示。

type Page struct {
	Title  string `form:"title" binding:"required"`
	Active bool
}

func (p *Page) UnmarshalJSON(bytes []byte) error {
	var data map[string]interface{}
	err := json.Unmarshal(bytes, &data)
	if err != nil {
		return err
	}
	actv, _ := data["active"]
	if reflect.TypeOf(actv).Kind() != reflect.Bool {
		return errors.New("active field should be a boolean")
	}

	p.Active = actv.(bool)

	return nil
}

Playground中查看完整示例。

英文:

Write custom JSON Unmarshaller method for the type Page and inside UnmarshalJSON(bytes []byte) method, you can unmarshal the JSON bytes to map[string]interface{} and then validate the types you need with the JSON field keys.

An example of the JSON Unmarshaller looks like below.

type Page struct {
	Title  string `form:"title" binding:"required"`
	Active bool
}

func (p *Page) UnmarshalJSON(bytes []byte) error {
	var data map[string]interface{}
	err := json.Unmarshal(bytes, &data)
	if err != nil {
		return err
	}
	actv, _ := data["active"]
	if reflect.TypeOf(actv).Kind() != reflect.Bool {
		return errors.New("active field should be a boolean")
	}

	p.Active = actv.(bool)

	return nil
}

See the full example here in Playground.

答案2

得分: 1

经过进一步的研究,我已经实现了Go-map-schema

var page Page
src := make(map[string]interface{})
json.Unmarshal(jsonData, &src)

results, _ := schema.CompareMapToStruct(page, src, nil)

fmt.Println(results.MissingFields)
fmt.Println(results.MismatchedFields)

这个代码片段使用了结构体的标准表示方式:

type Page struct {
	Title  string `json:"title" validator:"required"`
	Active bool   `json:"metaRobotsFollow" validate:"required,bool"`
}
英文:

After some more research, I've implemented Go-map-schema.

var page Page
src := make(map[string]interface{})
json.Unmarshal(jsonData, &src)

results, _ := schema.CompareMapToStruct(page, src, nil)

fmt.Println(results.MissingFields)
fmt.Println(results.MismatchedFields)

This works simple with the standard notations for an struct:

type Page struct {
	Title  string `json:"title" validator:"required"`
	Active bool   `json:"metaRobotsFollow" validate:"required,bool"`
}

答案3

得分: 0

你应该使用Go中可用的validator v10。

validator文档go

对于你的用例,你可以使用boolean验证器。
https://pkg.go.dev/github.com/go-playground/validator/v10#hdr-Boolean

type Page struct {
    Title  string `json:"title" binding:"required"`
    Active bool   `json:"active" binding:"required,boolean"`
}

以下是一个带有一个正向和一个负向测试用例的示例:

func TestPage(t *testing.T) {
    tests := []struct {
        testName string
        input    string
        wantErr  bool
    }{
        {
            testName: "positive test",
            input: `{
                "title": "first book title",
                "active": false
            }`,
            wantErr: false,
        }, {
            testName: "wrong boolean",
            input: `{
                "title": "second book title",
                "active": falsee
            }`,
            wantErr: false,
        },
    }

    for _, tt := range tests {
        t.Run(tt.input, func(t *testing.T) {
            var p Page
            b := []byte(tt.input)
            err := json.Unmarshal(b, &p)
            assert.Nil(t, err, "got error %v", err)
        })
    }
}
英文:

You should use validator v10 available with Go

validator documentation go

For your use case you can use boolean validator
https://pkg.go.dev/github.com/go-playground/validator/v10#hdr-Boolean

type Page struct {
  Title  string `json:"title" binding:"required"`
  Active bool   `json:"active" binding:"required,boolean"`
}

Below is sample Test case with one positive and negative

func TestPage(t *testing.T) {

tests := []struct {
	testName string
	input    string
	wantErr  bool
}{
	{
		testName: "positive test",
		input: `{
				 "title": "first book title",
				  "active": false
				}`,
		wantErr: false,
	}, {
		testName: "wrong boolean",
		input: `{
				 "title": "second book title",
				  "active": falsee
				}`,
		wantErr: false,
	},
}

for _, tt := range tests {
	t.Run(tt.input, func(t *testing.T) {
		var p Page
		b := []byte(tt.input)
		err := json.Unmarshal(b, &p)
		assert.Nil(t, err, "got error %v", err)
	})
}

huangapple
  • 本文由 发表于 2022年8月10日 20:19:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/73306221.html
匿名

发表评论

匿名网友

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

确定