繁体   English   中英

Golang:验证字符串类型的结构字段为特定值之一

[英]Golang: Validate Struct field of type string to be one of specific values

golang 版本: 1.18.3

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

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

{
  "name": "Duro",
  "gender": "MALE",
  "tier": 3,
  "mobileNumber": "0356874586",
  "address": {
    "city": "Tokyo",
    "street": "Shibaura St"
  },
  "children":[
    {
      "title": "Mr",
      "lastName": "Takayashi"
    }
  ],
  "isEmployed": false,
  "requestedAt": "2022-01-10T03:30:12.639Z"
}

这是我的 user.go 文件,

package main

type User struct {
        Name                   string                     `validate:"required"`
        Gender                 string                     `validate:"required,oneof=MALE FEMALE"`
        Tier                   *uint8                     `validate:"required,eq=0|eq=1|eq=2|eq=3"`
        MobileNumber           string                     `validate:"required"`
        Email                  string
        Address                *Address  `validate:"required"`
        Children               []Child   `validate:"required,dive"`
        IsEmployed             *bool     `validate:"required"`
        PreferredContactMethod string    `validate:"oneof=EMAIL PHONE POST SMS"`
        RequestedAt            time.Time `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) {
    validate := validator.New()
    var u User

    err := json.Unmarshal([]byte(jsonData), &u)
    if err != nil {
        panic(err)
    }

    err := validate.Struct(&u)
    if err != nil {
        t.Errorf("error %v", err)
    }

}

此测试因错误而失败,

error Key: 'User.PreferredContactMethod' Error:Field validation for 'PreferredContactMethod' failed on the 'oneof' tag

发生这种情况是因为 Go 将空字符串分配给 User.PreferredContactMethod 结构字段。 由于PreferredContactMethod不是必填字段,因此当 json 有效负载没有它时,我不想看到此验证错误。 当 json 有效负载没有preferredContactMethod字段时,如何避免此错误消息?

如果您有更好的选择来实现此验证,也很高兴听到它们。

这是Go Playground 中的代码

使用omitemptyoneof使验证器库忽略空值或未设置值。

type User struct {
        Name                   string                     `validate:"required"`
        Gender                 string                     `validate:"required,oneof=MALE FEMALE"`
        Tier                   *uint8                     `validate:"required,eq=0|eq=1|eq=2|eq=3"`
        MobileNumber           string                     `validate:"required"`
        Email                  string
        Address                *Address  `validate:"required"`
        Children               []Child   `validate:"required,dive"`
        IsEmployed             *bool     `validate:"required"`
        PreferredContactMethod string    `validate:"omitempty,oneof=EMAIL PHONE POST SMS"`
        RequestedAt            time.Time `validate:"required"`
    }

使用https://github.com/marrow16/valix ( https://pkg.go.dev/github.com/marrow16/valix ) 可以通过以下方式实现:

package main

import (
    "fmt"
    "time"

    "github.com/marrow16/valix"
)

type User struct {
    Name                   string    `json:"name" v8n:"required, notNull"`
    Gender                 string    `json:"gender" v8n:"required, notNull, &strtoken{['MALE','FEMALE']}"`
    Tier                   uint8     `json:"tier" v8n:"required, notNull, &mini{0}, &maxi{3}"`
    DateOfBirth            string    `json:"dateOfBirth" v8n:"notNull, &strisod"`
    MobileNumber           string    `json:"mobileNumber" v8n:"required, notNull, &strpatt{'^([0-9]{8,16})$'}"`
    Email                  string    `json:"email" v8n:"notNull"`
    Address                Address   `json:"address" v8n:"required, notNull"`
    Children               []Child   `json:"children" v8n:"required, notNull"`
    IsEmployed             bool      `json:"isEmployed" v8n:"required"`
    PreferredContactMethod string    `json:"preferredContactMethod" v8n:"notNull, &strtoken{['EMAIL','PHONE','POST','SMS']}"`
    RequestedAt            time.Time `json:"requestedAt" v8n:"required, notNull, &strisodt"`
}
type Address struct {
    City   string `json:"city" v8n:"required, notNull"`
    Street string `json:"street" v8n:"required, notNull"`
}

type Child struct {
    Title     string `json:"title" v8n:"required, notNull"`
    FirstName string `json:"firstName" v8n:"notNull"`
    LastName  string `json:"lastName" v8n:"required, notNull"`
}

const jsonData = `{
  "name": "Duro",
  "gender": "MALE",
  "tier": 3,
  "dateOfBirth": "2000-01-13",
  "mobileNumber": "0356874586",
  "address": {
    "city": "Tokyo",
    "street": "Shibaura St"
  },
  "children":[
    {
      "title": "Mr",
      "lastName": "Takayashi"
    }
  ],
  "isEmployed": false,
  "requestedAt": "2022-01-10T03:30:12.639Z"
}`

var UserRequestValidator = valix.MustCompileValidatorFor(User{}, nil)

func main() {
    user := User{}

    ok, violations, _ := UserRequestValidator.ValidateStringInto(jsonData, &user)

    if ok {
        fmt.Println("Validation successful")
    } else {
        fmt.Println(fmt.Sprintf("Validation failed! (violations: %d)", len(violations)))
        for _, v := range violations {
            fmt.Printf("%s (property: '%s', path: '%s')\n", v.Message, v.Property, v.Path)
        }
    }
}

去游乐场: https ://go.dev/play/p/3zrkZx97m-e

披露:我是 Valix 的作者

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM