[英]Golang: Validate Struct field of type string to be one of specific values
[英]Golang: Validate inner Struct field based on the values of one of its enclosing struct's field using required_if tag
golang 版本: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"
}
}
這是我的醫療保險。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"`
}
這是我的測試 function
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)
}
}
我想使用驗證器/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-solution ,自定義驗證的文檔可在此處獲取https://pkg.go.dev/github.com/go-playground/validator#CustomTypeFunc
。
有點老的問題,但 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)
}
}
在運動場上
披露:我是 Valix 的作者
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.