簡體   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