Echo: Regression: binding a map is not allowed anymore

Created on 10 Aug 2017  Â·  20Comments  Â·  Source: labstack/echo

Issue Description

I think a valid use case of binding to a map[string]interface{} now causes the following error: Binding element must be a struct. I think the regression has been caused by #972.

Is this use case still valid ?

Checklist

  • [x] Dependencies installed
  • [x] No typos
  • [x] Searched existing issues and docs

Expected behaviour

Binding a map[string]interface{} is valid.

Actual behaviour

Binding a map[string]interface{} causes an error.

Code to debug

package main

func handler(c echo.Context) {
  var m map[string]interface{}
  if err := c.Bind(&m); err != nil {
    // err is "Binding element must be a struct"
  }
  return nil
}

Version/commit

1e9845a414f5177986779ee21963df7d1e362e15

bug

All 20 comments

Has this issue been solved? I meet it today. my code as following:

maybe you need to repear it locally since go playground cannot listen port.
@vishr

Has this issue been solved? I meet it today. my code as following:

maybe you need to repear it locally since go playground cannot listen port.
@vishr

me too

I am not sure what is the issue but the following code works

package main

import (
    "net/http"
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/test", func(c echo.Context) error {
        p := map[string]interface{}{}
        if err := c.Bind(&p); err != nil {
            return err
        }
        return c.JSON(http.StatusOK, p)
    })

    e.Start("127.0.0.1:8080")
}
curl -X GET \
  http://localhost:8080/test \
  -H 'Content-Type: application/json' \
  -d '{
    "a": 1,
    "b": 2
}'

thanks for your reply,
and your eg works fine.
it seems that bind to map only works when content-type is application/json, does it?

How are you sending the data?

i've tested both following format:

  • curl -X GET -H 'Content-Type: application/x-www-form-urlencoded' http://localhost:8080/test?a=1&b=2
  • curl -X GET http://localhost:8080/test -H 'Content-Type: application/x-www-form-urlencoded' -d 'a=1&b=2'

and echo returns binding element must be a struct error.

after a deep dive to echo.
I find that ctx.Bind returns err in some situation with a map destination.

Do it possible to support Map in DefaultBinder? or this will cause some other issues? @vishr

@narrowizard Just push a fix, let me know how it works out for you.

it works now except that it causes a panic if ptr is of type map[string]interface{} with nil value. it's better to add an nil check before set value.
https://github.com/labstack/echo/blob/da459814916905d4ea1208ded02f15924fa6a114/bind.go#L97-L98

var p map[string]interface
ctx.Bind(&p) // here panic `assignment to entry in nil map`

anyway, thanks for your impl. @vishr

Fixed.

On Jul 14, 2019, at 10:36 PM, NaRro notifications@github.com wrote:

it works now except that it causes a panic if ptr is of type map[string]interface{} with nil value. it's better to add an nil check before set value.
https://github.com/labstack/echo/blob/da459814916905d4ea1208ded02f15924fa6a114/bind.go#L97-L98 https://github.com/labstack/echo/blob/da459814916905d4ea1208ded02f15924fa6a114/bind.go#L97-L98
var p map[string]interface
ctx.Bind(&p) // here panic assignment to entry in nil map
anyway, thanks for your impl. @vishr https://github.com/vishr
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/labstack/echo/issues/988?email_source=notifications&email_token=AACMVNG7NDBELHXZYYOELRDP7QEFBA5CNFSM4DWOQOB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZ4X7NY#issuecomment-511279031, or mute the thread https://github.com/notifications/unsubscribe-auth/AACMVNBKBP6QJOHLLMTT3XTP7QEFBANCNFSM4DWOQOBQ.

Well, it looks like binding a map can still panic with echo v4.1.10: https://travis-ci.org/cozy/cozy-stack/jobs/573823462#L696-L703. The code is in this PR: https://github.com/cozy/cozy-stack/pull/2015.

@nono I will look into this today.

@vishr
I also encountered this kind of problem.
If i send Post request with same json file, everything is ok.
But if i send Put request with same json file, error on parsing

m := echo.Map{}
fmt.Printf("\n\n confirmOrCancelPaymentOrder ENTERED")
if err := c.Bind(&m); err != nil {
    fmt.Printf("\n PARSING ERROROROROOR \n")
    return err
}

Folks, I need help here. Let me know if you are willing to contribute.

@vishr

  1. this happen in latest version of Echo
    s.PUT("/users/:id", func(c echo.Context) error

  2. Also this happen when add :id param in url.

RESPONSE BODY: {"message":"binding element must be a struct"}
RESPONSE STATUS: 400 Bad Request

Solved, this is working for me:

order struct {
  ID    int    `json:"id" param:"id"`
  State string `json:"state"`
}

e := echo.New()
e.Use(middleware.Logger())
e.PUT("/orders/:id", confirmOrder)

//JSON:
// PUT /orders/{id}
// {"state": "CONFIRM"}

ord := order{}
if err := c.Bind(&ord); err != nil {
  log.Fatal(err)
}
log.Print(ord)
return nil

I have the same problem with using the :id param and PUT/PATCH/POST and Bind(). It only works with version 4.1.6 or older..
I am sending a JSON Body with Content-Type application/json to a route: /api/path/:id

I'm having this problem with echo v4.1.11. When I have this code:

callbackURL := ctx.QueryParam("callback")

payload := echo.Map{}

err := ctx.Bind(&payload)

This produces the error:

binding element must be a struct

If I remove the callbackURL line, it binds just fine. Anyone have any clues as to what's going on here?

Thank you, @vishr. It works for me.

Same problem here with Echo v4.1.11

month := c.Param("month")
var lines []models.CLinesToUpdate
if err := c.Bind(&lines); err != nil {

=> binding element must be a struct

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zzwx picture zzwx  Â·  14Comments

mandeepbrar picture mandeepbrar  Â·  22Comments

yaa110 picture yaa110  Â·  39Comments

vishr picture vishr  Â·  64Comments

lon9 picture lon9  Â·  11Comments