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"

screen shot 2016-12-04 at 10 56 58 am

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: 2017-07-18 12 09 57

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