Golang: Validate Struct Fields in Slice Items

Issue

I’m new to Golang.

golang version: 1.17.8

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": "Yomiko",
  "address": {
    "city": "Tokyo",
    "street": "Shibaura St"
  },
  "children":[
    {
      "lastName": "Takayashi"
    }
  ],
  "isEmployed": false
  }

Here’s my user.go file,

package main

type User struct {
    Name    string
    Address *Address `validate:"required"`
    Children []*Child
    IsEmployed *bool `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) {
    actualUserPayload := NewUserPayloadFromFile("userpayload.json")

    validate := validator.New()
    err := validate.Struct(actualUserPayload)
    if err != nil {
        t.Error("Validation Error: ", err)
    }

}

This test passes. However, I expected it to fail as Child.Title is marked as required. I expected the following error,

Validation Error:  Key: 'Child.Title' Error:Field validation for 'Title' failed on the 'required' tag

However, when I loop through the children slice and validate each child struct as follows the test fails as expected,

func TestUserPayload(t *testing.T) {
    actualUserPayload := NewUserPayloadFromFile("userpayload.json")

    validate := validator.New()
    err := validate.Struct(actualUserPayload)
    if err != nil {
        t.Error("Validation Error: ", err)
    }

    children := actualUserPayload.Children

    for _, child := range children {
        err := validate.Struct(child)
        if err != nil {
            t.Error("Validation Error: ", err)
        }
    }

}

Is there a straightforward way to do this validation of the items in a slice of structs?

Solution

According to the documentation of the validator package, you can use dive in your struct tag to get this behavior. This causes the validator to also validate the nested struct/slice/etc.

So you would need to update your User struct to this:

type User struct {
    Name       string
    Address    *Address `validate:"required"`
    Children   []*Child `validate:"dive"`
    IsEmployed *bool    `validate:"required"`
}

Here it is working in Go Playground

Answered By – phonaputer

Answer Checked By – David Goodson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.