为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕姐4208626 2023-01-03 16:20:11
高朗版本: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 mainimport (    "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 代码
查看完整描述

2 回答

?
慕虎7371278

TA贡献1802条经验 获得超4个赞

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



查看完整回答
反对 回复 2023-01-03
?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

有点老的问题,但是 valix ( https://github.com/marrow16/valix ) 可以使用条件“开箱即用”地做这些事情。例子...


package main


import (

    "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)

    }

}

游乐场_


查看完整回答
反对 回复 2023-01-03
  • 2 回答
  • 0 关注
  • 713 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信