package main
import "log"
import "github.com/gin-gonic/gin"
type Person struct {
Name string `json:"name"`
Address string `json:"address"`
}
func main() {
log.Println("Hello World")
route := gin.Default()
route.GET("/testing", startPage)
route.Run(":8085")
}
func startPage(c *gin.Context) {
var person Person
if c.BindJSON(&person) == nil {
log.Println(person.Name)
log.Println(person.Address)
log.Println("Binding success...............")
} else {
log.Println("Binding failed...............")
}
c.String(200, "Success")
}
The above code works only for curl -X GET localhost:8085/testing --data '{"name":"JJ", "address":"xyz"}' -H "Content-Type:application/json"
but not curl -X GET localhost:8085/testing?name=JJ&address=xyz -H "Content-Type:application/json"
if i use c.Bind(&person)
, binding failed both case.
How can i write the above code which binds both query string and json.
Comment From: ei-grad
+1 for c.BindQuery
Comment From: appleboy
We don't need c.BindQuery
.
Try c.Bind
for query string and post data:
type Person struct {
Name string `form:"name"`
Address string `form:"address"`
}
Try c.BindJSON
for JSON data:
type Person struct {
Name string `json:"name"`
Address string `json:"address"`
}
Comment From: jasonab
Looking over the binding code, I don't see anywhere that it accesses req.URL.Query(). I don't understand how we can bind query parameters without that.
Comment From: ei-grad
@jasonab it uses http.Request.Form, which contains query params.
@appleboy thanks! This is absolutely not clear from docs. :-(
Comment From: jasonab
@ei-grad Thanks, that was non-obvious :-)
Comment From: appleboy
The following example is working for me.
package main
import "log"
import "github.com/gin-gonic/gin"
type Person struct {
Name string `form:"name" json:"name"`
Address string `form:"address" json:"address"`
}
func main() {
route := gin.Default()
route.GET("/testing", startPage)
route.Run(":8085")
}
func startPage(c *gin.Context) {
var person Person
if c.Bind(&person) == nil {
log.Println("====== Bind By Query String ======")
log.Println(person.Name)
log.Println(person.Address)
}
if c.BindJSON(&person) == nil {
log.Println("====== Bind By JSON ======")
log.Println(person.Name)
log.Println(person.Address)
}
c.String(200, "Success")
}
And try the following command:
# bind by query
$ curl -X GET "localhost:8085/testing?name=appleboy&address=xyz"
# bind by json
$ curl -X GET localhost:8085/testing --data '{"name":"JJ", "address":"xyz"}' -H "Content-Type:application/json"
You can find the example from the following URL:
https://github.com/gin-gonic/gin#model-binding-and-validation
Maybe we need to add bind query example on documents. 😄
Comment From: appleboy
@jasonab @ei-grad I will update document asap.
Comment From: ei-grad
Maybe we need to add bind query example on documents. 😄
It would be great.
Comment From: deankarn
What if you posted values and had query string params how would you only parse/bind the query string params.
Bind always uses r.Form which is a combination of posted values and query params...same goes for only wanting to parse/bind r.PostForm and not wanting query string.
Comment From: mehdy
+1 for BindQuery
Comment From: appleboy
@mehdy See the comment https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292
Comment From: appleboy
I make new PR to improve document. https://github.com/gin-gonic/gin/pull/772
Comment From: deankarn
So @appleboy if you posted data and had Query string params how could you ONLY bind the Query string params or ONLY bind posted data?
It seems like my previous comment was just overlooked.
Comment From: appleboy
https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292
Do you see the screenshot?
only bind the query or post data
if c.Bind(&person) == nil {
log.Println("====== Bind By Query String ======")
log.Println(person.Name)
log.Println(person.Address)
}
only bind the json data
if c.BindJSON(&person) == nil {
log.Println("====== Bind By JSON ======")
log.Println(person.Name)
log.Println(person.Address)
}
Comment From: deankarn
Yes @appleboy I did see the screenshot,
your example is for Query params and JSON and my example was posting Form Data and Query params.
What if someone wanted to ONLY bind the Query Params and not the form data.
Comment From: mehdy
that's exactly the point! I think we need an BindQuery
function that only binds the query params and not the post data in case some one is using both together
Comment From: easonlin404
Only Bind Query String
See PR https://github.com/gin-gonic/gin/pull/1029. Add c.BindQuery
function that only binds the query params and not the post data.
package main
import "log"
import "github.com/gin-gonic/gin"
type Person struct {
Name string `form:"name"`
Address string `form:"address"`
}
func main() {
route := gin.Default()
route.Any("/testing", startPage)
route.Run(":8085")
}
func startPage(c *gin.Context) {
var person Person
if c.BindQuery(&person) == nil {
log.Println("====== Only Bind Query String ======")
log.Println(person.Name)
log.Println(person.Address)
}
c.String(200, "Success")
}
Try the following command:
# only bind query
$ curl -X GET "localhost:8085/testing?name=eason&address=xyz"
# only bind query string, ignore form data
$ curl -X POST "localhost:8085/testing?name=eason&address=xyz" --data 'name=ignore&address=ignore' -H "Content-Type:application/x-www-form-urlencoded"
Will Output:
Comment From: javierprovecho
1029 merged
Comment From: xgz123
We don't need
c.BindQuery
.Try
c.Bind
for query string and post data:
go type Person struct { Name string `form:"name"` Address string `form:"address"` }
Try
c.BindJSON
for JSON data:
go type Person struct { Name string `json:"name"` Address string `json:"address"` }
bindQuery also works with "form" tag
Comment From: tprei
does this only work with shouldBindQuery
? I am using shouldBindWith(..., binding.Query)
and it's outputing and error for a missing reuired
json tag
I think shouldBindWith
should have the same behaviour
Comment From: Linhieng
I arrived here from this URL, and then this reproduces it, and finds that it is different from the above output
Whether I send a request with query or json, he recognizes it as a json type.
$ curl -X GET localhost:8085/testing --data '{"name":"JJ", "address":"xyz"}' -H "Content-Type:application/json"
Successcurl: (3) unmatched close brace/bracket in URL position 12:
address:xyz}'
^
and now I ignored the argument and passed an empty piece of data:
$ curl -X GET localhost:8085/testing --data "" -H "Content-Type:application/json"
Success
but in the terminal:
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200
[GIN] 2022/05/16 - 17:13:11 | 200 | 3.1717ms | 127.0.0.1 | GET "/testing"
2022/05/16 17:16:10 ====== Bind By Query String ======
2022/05/16 17:16:10
2022/05/16 17:16:10
Is anyone having the same problem as me?
Comment From: Mai-Lapyst
I arrived here from this URL, and then this reproduces it, and finds that it is different from the above output
Whether I send a request with query or json, he recognizes it as a json type.
shell $ curl -X GET localhost:8085/testing --data '{"name":"JJ", "address":"xyz"}' -H "Content-Type:application/json" Successcurl: (3) unmatched close brace/bracket in URL position 12: address:xyz}' ^
and now I ignored the argument and passed an empty piece of data:
shell $ curl -X GET localhost:8085/testing --data "" -H "Content-Type:application/json" Success
but in the terminal:
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200 [GIN] 2022/05/16 - 17:13:11 | 200 | 3.1717ms | 127.0.0.1 | GET "/testing" 2022/05/16 17:16:10 ====== Bind By Query String ====== 2022/05/16 17:16:10 2022/05/16 17:16:10
Is anyone having the same problem as me?
There are serveral things wrong here:
- First of, body data in a GET
request is by a bunch of frameworks not supported (or atleast not fully) since also the HTTP spec dosnt want you to send data when using GET
; thats what they designed POST
, PUT
, PATCH
for.
- Curl respects the point above and tries to encode your data into the URL instead of the body, hence you get the "unmatched close brace/bracket in URL" error.
- When ignoring the data (you simply give it an empty string) it therefore also dosnt send any data (either body nor query) and therefore your output also have empty lines, since again: your data is empty as well.
Hope this could help you