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(¶ms); 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.Id
uri:"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(¶ms); 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 } ```