Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bind JSON and URI #1824

Closed
montanaflynn opened this issue Mar 24, 2019 · 7 comments
Closed

Bind JSON and URI #1824

montanaflynn opened this issue Mar 24, 2019 · 7 comments

Comments

@montanaflynn
Copy link

Description

I'm trying to bind JSON and a URI in one request but havn't found out how to yet.

Here's my struct:

type ResetPassword struct {
	Code     string `uri:"code" binding:"required"`
	Password string `json:"password" binding:"required,min=6,max=20"`
}

I'm using c.Bind():

func verifyPasswordReset(c *gin.Context) {
	var data ResetPassword
	if err := c.Bind(&data); err != nil {
		c.JSON(400, gin.H{"error": err})
		return
	}
	fmt.Printf("%+v\n", data)
	c.JSON(http.StatusOK, data)
}

When I make this request it says the code is required:

curl -H "content-type:application/json" -d '{"password":"hunter15"}' "localhost:8080/user/password_reset/jksakhdkh"                                                                     Sun Mar 24 14:29:27 2019
{"error":{".Code":{"FieldNamespace":".Code","NameNamespace":"Code","Field":"Code","Name":"Code","Tag":"required","ActualTag":"required","Kind":24,"Type":{},"Param":"","Value":""}}}

I found a related issue #811 but it wasn't actually solved before being closed.

@thinkerou
Copy link
Member

you should split bind uri and json to two struct.

@montanaflynn
Copy link
Author

@thinkerou ok, I split it into two structs and used the respective binds:

	if err := c.ShouldBindUri(&dataURI); err != nil {
		c.JSON(400, gin.H{"error": err})
		return
	}

	if err := c.ShouldBindJSON(&dataJSON); err != nil {
		c.JSON(400, gin.H{"error": err})
		return
	}

That works fine and removes my workaround of using c.Params.ByName("code"), thanks!

@m430
Copy link

m430 commented Jun 6, 2020

@thinkerou Why not use the uri and form tag together? I think it would be convenient.

@invisibleDesigner
Copy link

no, I want to use it in one struct

@chengr4
Copy link

chengr4 commented Jun 13, 2023

At 2023, we still should split it into two structs?

@TaylorDurden
Copy link

TaylorDurden commented Jul 17, 2024

At 2023, we still should split it into two structs?
Here is a example:

type updateAccountRequest struct {
	ID      int64 `uri:"id" binding:"required,min=1"`
	Balance int64 `json:"balance"`
}

func (server *Server) updateAccountHandler(ctx *gin.Context) {
	var req updateAccountRequest
	if err := ctx.ShouldBindUri(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, errorResponse(err))
		return
	}

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, errorResponse(err))
		return
	}
	arg := db.UpdateAccountParams{
		ID:      req.ID,
		Balance: req.Balance,
	}
	updatedAccount, err := server.store.UpdateAccount(ctx, arg)
	if err != nil {
		if err == sql.ErrNoRows {
			ctx.JSON(http.StatusNotFound, errorResponse(err))
			return
		}
		ctx.JSON(http.StatusInternalServerError, errorResponse(err))
		return
	}

	ctx.JSON(http.StatusOK, updatedAccount)
}

@QingShan-Xu
Copy link

Balance int64 json:"balance"

If you set Balance int64 json:"balance" binding:"required", it will still fail because shoudBindUri binds json:"balance" but there is no balance in the uri.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants