Description
Trying to bind a struct with nested slice of struct. I have looked into following issues and tried them but still getting nil for the nested slice of struct.
- Bind form-data request with nested structures #551
- Add validating sub structures #224
- Gin binding in Go: A tutorial with examples
How to reproduce
type Attribute struct {
AttributeName string `json:"attributeName" bson:"attributeName" validate:"required" binding:"required"`
Type string `json:"type" bson:"type" validate:"required" binding:"required"`
IsRequired bool `json:"isRequired" bson:"isRequired" validate:"required" binding:"required"`
Min int `json:"min" bson:"min" validate:"required" `
Max int `json:"max" bson:"max" validate:"required" `
}
type FamilyConfig struct {
Name string `json:"name" bson:"name" validate:"required" binding:"required"`
Attributes []Attribute `json:"attributes" bson:"attributes" validate:"dive" binding:"required,dive"`
}
func PostFamilyConfig(c *gin.Context) {
var familyConfig FamilyConfig
err := c.ShouldBind(&familyConfig)
if err != nil {
log.Fatal(err)
}
log.Printf("Request data: %#v\n", familyConfig)
c.JSON(http.StatusOK, familyConfig)
}
Expectations
$ curl --location 'localhost:8080/family-config' \
--header 'Content-Type: application/json' \
--data '{
"name": "Toy",
"attributes": [
{
"attributeName": "color",
"type": "text",
"isRequired": true,
"min": 0,
"max": 9
},
{
"attributeName": "test",
"type": "html",
"isRequired": true,
"min": 0,
"max": 9
}
]
}'
status: 200 Ok
{
"name": "Toy",
"attributes": [
{
"attributeName": "color",
"type": "text",
"isRequired": true,
"min": 0,
"max": 9
},
{
"attributeName": "test",
"type": "html",
"isRequired": true,
"min": 0,
"max": 9
}
]
}
Actual result
In the log.Printf I am getting nil for Attributes
$ Request data: familyConfigHandlers.FamilyConfig{Name:"lipstick", Attributes:[]*familyConfigHandlers.Attribute(nil)}
Environment
- go version: 1.20
- gin version (or commit ref): 1.9.0
- operating system: Windows 10 Pro build: 19045.2728
Comment From: shplume
I just copy your code and run it, but the result is correct. You can see it below. And my environment is the same as yours. Maybe
you should look for an error somewhere else.
Result
Comment From: iamsubrataaich
I checked my code again and still getting nil. Did not find any error.
package main
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
)
type Attribute struct {
AttributeName string `json:"attributeName" bson:"attributeName" validate:"required" binding:"required"`
Type string `json:"type" bson:"type" validate:"required" binding:"required"`
IsRequired bool `json:"isRequired" bson:"isRequired" validate:"required" binding:"required"`
Min int `json:"min" bson:"min" validate:"required" `
Max int `json:"max" bson:"max" validate:"required" `
}
type FamilyConfig struct {
Name string `json:"name" bson:"name" validate:"required" binding:"required"`
Attributes []Attribute `json:"attributes" bson:"attributes" validate:"dive" binding:"dive"`
}
func main() {
server := gin.Default()
server.POST("/family-config", PostFamilyConfig)
server.Run()
}
func PostFamilyConfig(c *gin.Context) {
var r = c.Request.Body
log.Print(r)
var familyConfig FamilyConfig
err := c.ShouldBindJSON(&familyConfig)
if err != nil {
c.AbortWithError(400, err)
log.Fatal(err)
}
log.Printf("Request data: %#v\n", familyConfig)
c.JSON(http.StatusOK, familyConfig)
}
Comment From: iamsubrataaich
I ran the application in a Ubuntu 22.04 virtual box and it is running as expected as @shplume said. I still can't find what is wrong with it when I am running it on my windows machine. I uninstalled Go and deleted the go folder then installed go again and tried. But still getting the error.
Comment From: shplume
I copied your code again and ran it on my windows machine. But the result was not changed, my environment is windows 10 Home build: 19045.2846. I‘m sorry that I can't help you more.
Comment From: sahinmurat
you forget r in attRibute :). Your code is attibute not attribute :)