Golang:使用 required_if 标记根据其封闭结构字段之一的值验证内部结构字段

高朗版本:1.18.3


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


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


 {

        "irn": 1,

        "firstName": "Testing",

        "lastName": "Test",

        "cardType": "RECIPROCAL",

        "number": "2248974514",

        "cardExpiry": {

            "month": "01",

            "year": "2025"

        }

}

这是我的 medicare.go 文件


 package main


import (

    "encoding/json"


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

)


type Medicare struct {

    IRN           uint8

    FirstName     string

    MiddleInitial string

    LastName      string

    CardType      string `validate:"required,eq=RESIDENT|eq=RECIPROCAL|eq=INTERIM"`

    Number        string

    CardExpiry    *CardExpiry `validate:"required"`

}


type CardExpiry struct {

    Day   string

    Month string `validate:"required"`

    Year  string `validate:"required"`

}

这是我的测试功能


    func TestUserPayload(t *testing.T) {

    var m Medicare


    err := json.Unmarshal([]byte(jsonData), &m)

    if err != nil {

        panic(err)

    }


    validate := validator.New()

    err = validate.Struct(m)

    if err != nil {

        t.Errorf("error %v", err)

    }

}

我想使用 validator/v10 的required_if标记进行以下验证。这是验证逻辑,


if (m.CardType == "RECIPROCAL" || m.CardType == "INTERIM") &&

    m.CardExpiry.Day == "" {

    //validation error

}

required_if可以基于同一结构中的字段值使用(在本例中为 CardExpiry)


Day   string `validate:"required_if=Month 01"`

我的问题是,


可以根据其封闭结构字段之一(在本例中为 Medicare 结构)的值来完成吗?例如:


Day   string `validate:"required_if=Medicare.CardType RECIPROCAL"`

如果可以,怎么做?


这是go playground 代码


慕姐4208626
浏览 715回答 2
2回答

慕虎7371278

您可以编写自定义验证, playground-solution,自定义验证的文档可在此处获得https://pkg.go.dev/github.com/go-playground/validator#CustomTypeFunc。

翻过高山走不出你

有点老的问题,但是 valix ( https://github.com/marrow16/valix ) 可以使用条件“开箱即用”地做这些事情。例子...package mainimport (    "fmt"    "net/http"    "strings"    "github.com/marrow16/valix")type Medicare struct {    IRN           uint8  `json:"irn"`    FirstName     string `json:"firstName"`    MiddleInitial string `json:"middleInitial"`    LastName      string `json:"lastName"`    // set order on this property so that it is evaluated before 'CardExpiry' object is checked...    // (and set a condition based on its value)    CardType   string      `json:"cardType" v8n:"order:-1,required,&StringValidToken{['RESIDENT','RECIPROCAL','INTERIM']},&SetConditionFrom{Global:true}"`    Number     string      `json:"number"`    CardExpiry *CardExpiry `json:"cardExpiry" v8n:"required,notNull"`}type CardExpiry struct {    // this property is required when a condition of `RECIPROCAL` has been set (and unwanted when that condition has not been set)...    Day   string `json:"day" v8n:"required:RECIPROCAL,unwanted:!RECIPROCAL"`    Month string `json:"month" v8n:"required"`    Year  string `json:"year" v8n:"required"`}var medicareValidator = valix.MustCompileValidatorFor(Medicare{}, nil)func main() {    jsonData := `{        "irn": 1,        "firstName": "Testing",        "lastName": "Test",        "cardType": "RECIPROCAL",        "number": "2248974514",        "cardExpiry": {            "month": "01",            "year": "2025"        }    }`    medicare := &Medicare{}    ok, violations, _ := medicareValidator.ValidateStringInto(jsonData, medicare)    // should fail with 1 violation...    fmt.Printf("First ok?: %v\n", ok)    for i, v := range violations {        fmt.Printf("Violation[%d]: Message:%s, Property:%s, Path:%s\n", i+1, v.Message, v.Property, v.Path)    }    jsonData = `{            "irn": 1,            "firstName": "Testing",            "lastName": "Test",            "cardType": "RECIPROCAL",            "number": "2248974514",            "cardExpiry": {                "day": "01",                "month": "01",                "year": "2025"            }        }`    ok, _, _ = medicareValidator.ValidateStringInto(jsonData, medicare)    // should be ok...    fmt.Printf("Second ok?: %v\n", ok)    jsonData = `{            "irn": 1,            "firstName": "Testing",            "lastName": "Test",            "cardType": "INTERIM",            "number": "2248974514",            "cardExpiry": {                "month": "01",                "year": "2025"            }        }`    ok, _, _ = medicareValidator.ValidateStringInto(jsonData, medicare)    // should be ok...    fmt.Printf("Third ok?: %v\n", ok)    jsonData = `{            "irn": 1,            "firstName": "Testing",            "lastName": "Test",            "cardType": "INTERIM",            "number": "2248974514",            "cardExpiry": {                "day": "01",                "month": "01",                "year": "2025"            }        }`    ok, violations, _ = medicareValidator.ValidateStringInto(jsonData, medicare)    fmt.Printf("Fourth ok?: %v\n", ok)    for i, v := range violations {        fmt.Printf("Violation[%d]: Message:%s, Property:%s, Path:%s\n", i+1, v.Message, v.Property, v.Path)    }    // or validate directly from a http request...    req, _ := http.NewRequest("POST", "", strings.NewReader(jsonData))    ok, violations, _ = medicareValidator.RequestValidateInto(req, medicare)    fmt.Printf("Fourth (as http.Request) ok?: %v\n", ok)    for i, v := range violations {        fmt.Printf("Violation[%d]: Message:%s, Property:%s, Path:%s\n", i+1, v.Message, v.Property, v.Path)    }}游乐场_
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go