golang version: 1.18.3
validator: github.com/go-playground/validator/v10
I want to validate an incoming JSON payload after loaded into nested struct data structure. Here's my incoming JSON payload,
{
"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"
}
Here's my user.go file,
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"`
}
Here's my test function
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)
}
}
This test fails with error,
error Key: 'User.PreferredContactMethod' Error:Field validation for 'PreferredContactMethod' failed on the 'oneof' tag
This happens because Go assigns empty string to User.PreferredContactMethod struct field. Since PreferredContactMethod
is NOT a required field, I DON'T want to see this validation error when json payload doesn't have it. How can I avoid this error message when the json payload doesn't have preferredContactMethod
field?
If you have better alternatives to achieve this validation, happy to hear them as well.
Here's the code in Go Playground
Utilize omitempty
along with oneof
to make the validator library ignore empty or unset values.
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"`
}
Using https://github.com/marrow16/valix ( https://pkg.go.dev/github.com/marrow16/valix ) it could be achieved with the following:
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)
}
}
}
Go playground here: https://go.dev/play/p/3zrkZx97m-e
Disclosure: I am the author of Valix
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.