Golang:验证切片项中的结构字段

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

Golang: Validate Struct Fields in Slice Items

问题

我是你的中文翻译助手,以下是翻译好的内容:

我是Go语言的新手。

Go语言版本:1.17.8

验证器:github.com/go-playground/validator/v10

我想在将传入的JSON有效负载加载到嵌套的结构数据中后进行验证。这是我的传入JSON有效负载:

{
  "name": "Yomiko",
  "address": {
    "city": "Tokyo",
    "street": "Shibaura St"
  },
  "children":[
    {
      "lastName": "Takayashi"
    }
  ],
  "isEmployed": false
}

这是我的user.go文件:

package main

type User struct {
    Name       string
    Address    *Address `validate:"required"`
    Children   []*Child
    IsEmployed *bool `validate:"required"`
}

type Address struct {
    City    string `validate:"required"`
    Street  string `validate:"required"`
}

type Child struct {
    Title     string `validate:"required"`
    FirstName string
    LastName  string `validate:"required"`
}

这是我的测试函数:

func TestUserPayload(t *testing.T) {
    actualUserPayload := NewUserPayloadFromFile("userpayload.json")

    validate := validator.New()
    err := validate.Struct(actualUserPayload)
    if err != nil {
        t.Error("Validation Error: ", err)
    }
}

这个测试通过了。然而,我期望它会失败,因为Child.Title被标记为required。我期望出现以下错误:

Validation Error: Key: 'Child.Title' Error:Field validation for 'Title' failed on the 'required' tag

然而,当我遍历children切片并验证每个child结构时,测试会按预期失败:

func TestUserPayload(t *testing.T) {
    actualUserPayload := NewUserPayloadFromFile("userpayload.json")

    validate := validator.New()
    err := validate.Struct(actualUserPayload)
    if err != nil {
        t.Error("Validation Error: ", err)
    }

    children := actualUserPayload.Children

    for _, child := range children {
        err := validate.Struct(child)
        if err != nil {
            t.Error("Validation Error: ", err)
        }
    }
}

有没有一种简单直接的方法来验证结构体切片中的每个项?

英文:

I'm new to Golang.

golang version: 1.17.8

validator: "github.com/go-playground/validator/v10"

I want to validate an incoming JSON payload after loaded into nested struct data structure.
Here's my incoming JSON payload,

  {
  "name": "Yomiko",
  "address": {
    "city": "Tokyo",
    "street": "Shibaura St"
  },
  "children":[
    {
      "lastName": "Takayashi"
    }
  ],
  "isEmployed": false
  }

Here's my user.go file,

package main

type User struct {
	Name    string
	Address *Address `validate:"required"`
	Children []*Child
	IsEmployed *bool `validate:"required"`
}
type Address struct {
	City     string `validate:"required"`
	Street  string `validate:"required"`
}

type Child struct {
	Title string `validate:"required"`
	FirstName string
	LastName string `validate:"required"`
}

Here's my test function,

func TestUserPayload(t *testing.T) {
	actualUserPayload := NewUserPayloadFromFile("userpayload.json")

	validate := validator.New()
	err := validate.Struct(actualUserPayload)
	if err != nil {
		t.Error("Validation Error: ", err)
	}

}

This test passes. However, I expected it to fail as Child.Title is marked as required. I expected the following error,

Validation Error:  Key: 'Child.Title' Error:Field validation for 'Title' failed on the 'required' tag

However, when I loop through the children slice and validate each child struct as follows the test fails as expected,

func TestUserPayload(t *testing.T) {
	actualUserPayload := NewUserPayloadFromFile("userpayload.json")

	validate := validator.New()
	err := validate.Struct(actualUserPayload)
	if err != nil {
		t.Error("Validation Error: ", err)
	}

	children := actualUserPayload.Children

	for _, child := range children {
		err := validate.Struct(child)
		if err != nil {
			t.Error("Validation Error: ", err)
		}
	}

}

Is there a straightforward way to do this validation of the items in a slice of structs?

答案1

得分: 4

根据validator包的文档,你可以在结构体标签中使用dive来实现这个功能。这会导致验证器也会验证嵌套的结构体/切片等。

所以你需要将User结构体更新为以下内容:

type User struct {
	Name       string
	Address    *Address `validate:"required"`
	Children   []*Child `validate:"dive"`
	IsEmployed *bool    `validate:"required"`
}

Go Playground中可以看到它的工作示例。

英文:

According to the documentation of the validator package, you can use dive in your struct tag to get this behavior. This causes the validator to also validate the nested struct/slice/etc.

So you would need to update your User struct to this:

type User struct {
	Name       string
	Address    *Address `validate:"required"`
	Children   []*Child `validate:"dive"`
	IsEmployed *bool    `validate:"required"`
}

Here it is working in Go Playground

答案2

得分: 0

我正在使用Ginbinding:required,dive对我有效:

type Child struct {
  Name string `json:"name" binding:"required"`
}

type Body struct {
  Children []Child `json:"children" binding:"required,dive"`
}
英文:

I'm using Gin, binding:required,dive works for me:

type Child struct {
  Name string `json:"name" binding:"required"`
}

type Body struct {
  Children []Child `json:"children" binding:"required,dive"` 👈
}

huangapple
  • 本文由 发表于 2022年6月16日 08:49:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/72639302.html
匿名

发表评论

匿名网友

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

确定