Description

Based on https://github.com/gin-gonic/gin/issues/768#issuecomment-267978071 I can see that I can use the binding:"required" tag on nested structs. And indeed the following type definitions work and validate as one would expect:

type Nested struct {
    Inner string `json:"inner" binding:"required"`
}

type TestModel struct {
    Outer Nested `json:"outer" binding:"required"`
}

However if the outer type contains an array of inner type, e.g. Outer Nested -> Outer []Nested, the binding:"required" tag looses effect.

How to reproduce

package main

import (
    "github.com/gin-gonic/gin"
)

type Nested struct {
    Inner string `json:"inner" binding:"required"`
}

type TestModel struct {
    Outer []Nested `json:"outer" binding:"required"`
}

func main() {
    g := gin.Default()
    g.POST("/", func(c *gin.Context) {
        var model TestModel
                if c.ShouldBind(&model) == nil {
                    c.JSON(200, gin.H{"data": "valid"})
                } else {
                    c.JSON(400, gin.H{"data": "invalid"})
                }
    })
    g.Run(":9000")
}

Expectations

$ curl -H 'Content-Type: application/json' -X POST localhost:9000/ --data '{"outer": [{"missing": "foo"}]}'
{"data":"invalid"}

Actual result

$ curl -H 'Content-Type: application/json' -X POST localhost:9000/ --data '{"outer": [{"missing": "foo"}]}'
{"data":"valid"}

Environment

  • go version: go version go1.18.7 linux/amd64
  • gin version (or commit ref): github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
  • operating system: Linux x86_64 (Fedora 36)

Comment From: mstmdev

You should add the dive tag for the Outer field like the following code:

type TestModel struct {
    Outer []Nested `json:"outer" binding:"required,dive"`
}

Comment From: varesa

I can confirm it works, thanks!

I was going by the documentation/examples provided by gin (which bear no mention of dive, just grepped the website git repo), and didn't realize that I should have been looking at an entirely different package altogether.