Description

The binding:"required" tag does not seem to work to require a nested object in the json body. I have not been able to find documentation that show this is the expected behavior.

How to reproduce

package main

import (
    "fmt"

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

type Nested struct {
    Hello string `json:"hello"`
}

type TransferCreateBody struct {
    TestNested    Nested `json:"nested" binding:"required"`
    TestNotNested string `json:"not_nested" binding:"required"`
}

func main() {
    g := gin.Default()
    g.POST("/hello", func(c *gin.Context) {
        var req TransferCreateBody
        if err := c.ShouldBindJSON(&req); err != nil {
            fmt.Println(err)
            c.JSON(400, gin.H{"error": err.Error()})
            return
        }
        c.JSON(200, gin.H{"hello": req.TestNested.Hello})
    })
    g.Run(":9000")
}

For instance, a POST with body

{
    "not_nested": "test"
}

does not return an error even though the "nested" parameter is missing.

Expectations

curl -X POST http://localhost:9000/hello
   -H "Content-Type: application/json"
   -d '{"not_nested": "test"}'

expects an error because the "nested" tag is not present

Actual result

The request returns a 200 status. (if the "not_nested" parameter is absent, the server returns a 400 status as expected)

Environment

  • go version: 1.22.0
  • gin version (or commit ref): 1.9.1
  • operating system: mac OS 13.6.3

Comment From: jamesstocktonj1

This has been answered before here and you can fix it by making it a pointer as followed:

type TransferCreateBody struct {
    TestNested    *Nested `json:"nested" binding:"required"`
    TestNotNested string  `json:"not_nested" binding:"required"`
}

This results in a 400 response and {"error":"Key: 'TransferCreateBody.TestNested' Error:Field validation for 'TestNested' failed on the 'required' tag"}

Comment From: Pascal-Delange

Well, I stand corrected. Sorry for the duplicate post. However, if I may say, it's really hard to find documentation on how this is supposed to work :-) (in particular the other linked issues relating to the same question all seem to concern zero values of strings/ints, with the context I now understand it's the same cause, but without having the proper context it's not immediately obvious to search for it). Anyway, thanks for the answer !

Comment From: Pascal-Delange

well, while I'm at it, I posted a recap of the solution on stack overflow. Hope this can help others. https://stackoverflow.com/questions/78205172/go-gin-required-binding-seems-not-to-work-for-nested-structs/78205173#78205173