How to reproduce

package main

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

type UserRequest struct {
    Id       int    `uri:"id"`
    Nickname string `json:"nickname"`
    Mobile   string `json:"mobile"`
    Email    string `json:"email"`
}

func main() {
    g := gin.Default()
    g.GET("/user/:id", func(c *gin.Context) {
        // how to do?
    })
    g.Run(":9000")
}
curl -v -X POST \
  http://localhost:8080/user/12\
  -H 'content-type: application/json' \
  -d '{"nickname": "nickname1","mobile": "133232323232","email": "fqlw@qqq.com"

Comment From: Doarakko

Bind twice.

    g.POST("/user/:id", func(c *gin.Context) {
        var u UserRequest 

        if err := c.ShouldBindUri(&u); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        if err := c.ShouldBindJSON(&u); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        fmt.Printf("id: %d nickname: %s mobile: %s email: %s\n", u.Id, u.Nickname, u.Mobile, u.Email)

        c.JSON(http.StatusNoContent, nil)
    })

This is the related issue. https://github.com/gin-gonic/gin/issues/1824

Please tell me if there is another good way!

Comment From: lun3322

I also want to know if there is another way

Comment From: agmadt

Can't you do something like

u.ID = c.Param("id")?

Comment From: lun3322

It seems that it is not possible to bind successfully by calling the API once.

Comment From: tunhuit

Bind twice.

```go g.POST("/user/:id", func(c *gin.Context) { var u UserRequest

  if err := c.ShouldBindUri(&u); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
  }

  if err := c.ShouldBindJSON(&u); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
  }
  fmt.Printf("id: %d nickname: %s mobile: %s email: %s\n", u.Id, u.Nickname, u.Mobile, u.Email)

  c.JSON(http.StatusNoContent, nil)

}) ```

This is the related issue.

1824

Please tell me if there is another good way!

Only work with non-required fields. Is there anyway with required fields?

type UpdateRequest struct {
    ID   uint64 `uri:"id" binding:"required"`
    Data struct {
        Name string `json:"name" binding:"required"`
        Slug string `json:"slug" binding:"required"`
    }
}

Comment From: NicklasWallgren

As mentioned above, the workaround (bind twice) doesn't work with required fields.

Comment From: jlaneve

+1 on this. Any updates or workarounds for required fields?

Comment From: uedayuji

+1

Comment From: tiredsosha

+1

Comment From: murfidaz

+1

Comment From: neopoleones

+1

Comment From: alahaiyo

+1

Comment From: zhouguangming

+1

Comment From: c5ms

+1

Comment From: c5ms

ok here is an example :


// here ,we can use this struct in get method again.
type UserGetRequest struct {
    Id models.Id `uri:"id" binding:"required"`
}

type UserUpdateRequest struct {
    Nickname string `json:"nickname" `
}



func UserGet(context *gin.Context, domain *domains.Context) {
    var (
        locator = new(UserGetRequest)
    )

    if err = context.BindUri(locator); err != nil {
        return
    }

    if user, err = upms.UserGet(domain, locator.Id); err == nil {
         ... 
    }
    return
}


func UserUpdate(context *gin.Context)  {
    var (
                locator  = new(UserGetRequest)
        request = new(UserUpdateRequest)
    )

    if err = context.BindUri(&params); err != nil {
        return
    }

    if err = context.BindJSON(&request); err != nil {
        return
    }

    var action = upms.UserUpdateAction{
        Nickname: request.Nickname,
    }

    if user, err = upms.UserUpdate(domain, locator.Id, action); err == nil {
        .....
    }

    return
}

Comment From: abawchen

Is it a good idea to support something like requried_in=json, required_in=uri? If it makes sense, I would like to create a pr.

Comment From: KarlsMaranjs

This worked for me:

ok here is an example :

``go // here ,we can use this struct in get method again. type UserGetRequest struct { Id models.Iduri:"id" binding:"required"` }

type UserUpdateRequest struct { Nickname string json:"nickname" }

func UserUpdate(context *gin.Context) { var ( locator = new(UserGetRequest) request = new(UserUpdateRequest) )

if err = context.BindUri(&params); err != nil { return }

if err = context.BindJSON(&request); err != nil { return }

var action = upms.UserUpdateAction{ Nickname: request.Nickname, }

if user, err = upms.UserUpdate(domain, locator.Id, action); err == nil { ..... }

return } ```