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.

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

Gin Bind JSON body request with nested slice of struct

Gin Bind JSON body request with nested slice of struct

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 :)