samme4life
samme4life

Reputation: 1203

Golang: Validate Struct Fields in Slice Items

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?

Upvotes: 3

Views: 6958

Answers (2)

sareno
sareno

Reputation: 696

I'm using Gin, binding:required,dive works for me:

type Child struct {
  Name string `json:"name" binding:"required"`
}

type Body struct {
  Children []Child `json:"children" binding:"required,dive"` 👈
}

Upvotes: 0

phonaputer
phonaputer

Reputation: 1530

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

Upvotes: 4

Related Questions