Replies: 1 comment 4 replies
-
You can not specify to where body is bound. It is always bound directly to object referenced as At the moment I think shortest way to bind is: import (
"encoding/json"
"errors"
"github.com/labstack/echo/v4"
"log"
"net/http"
)
func main() {
e := echo.New()
e.POST("/:serviceURI/:endpointID/:applianceID", func(c echo.Context) error {
type DataPoint struct {
Name string `json:"name" validate:"required"`
Type string `json:"type" validate:"required"`
Value interface{} `json:"value" validate:"required"`
}
type Options struct {
EndpointID string `param:"endpointID"`
ApplianceID string `param:"applianceID"`
ServiceURI string `param:"serviceURI"`
Body []DataPoint
}
var opts Options
if err := json.NewDecoder(c.Request().Body).Decode(&opts.Body); err != nil {
return err
}
// we need to use BindPathParams because json.Decoder has already read the body
if err := (&echo.DefaultBinder{}).BindPathParams(c, &opts); err != nil {
return err
}
return c.JSON(http.StatusOK, opts)
})
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
} curl -v -X POST http://localhost:8080/serv/endp/applid -H 'Content-Type: application/json' -d '[{"name":"n1", "type":"t1", "value": true},{"name":"n2", "type":"t2", "value": "true"}]' But if you want to do same thing shorter you could create Binder like that type Binder struct {
binder echo.DefaultBinder
c echo.Context
err error
}
func NewBinder(c echo.Context) *Binder {
return &Binder{
c: c,
binder: echo.DefaultBinder{},
}
}
func (b *Binder) Error() error {
return b.err
}
func (b *Binder) BindPathParams(i interface{}) *Binder {
if b.err == nil {form+body)
b.err = b.binder.BindPathParams(b.c, i)
}
return b
}
func (b *Binder) BindBody(i interface{}) *Binder {
if b.err == nil {
// fixme: there should be check if we have not already read the request body (by double calling bindBody or binding
b.err = b.binder.BindBody(b.c, i)
}
return b
} and use it like that func main() {
e := echo.New()
e.POST("/:serviceURI/:endpointID/:applianceID", func(c echo.Context) error {
type DataPoint struct {
Name string `json:"name" validate:"required"`
Type string `json:"type" validate:"required"`
Value interface{} `json:"value" validate:"required"`
}
type Options struct {
EndpointID string `param:"endpointID"`
ApplianceID string `param:"applianceID"`
ServiceURI string `param:"serviceURI"`
Body []DataPoint
}
var opts Options
if err := NewBinder(c).BindPathParams(&opts).BindBody(&opts.Body).Error(); err != nil {
return err
}
return c.JSON(http.StatusOK, opts)
})
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
} |
Beta Was this translation helpful? Give feedback.
4 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Maybe I did not understand the documentation right, but what I want to do is to bind some path parameters and the whole body to a struct. Lets assume the struct like this:
The body contains a list of
DataPoint
objects, I want to bind them to theBody
field of the struct.I tested many things in the place of the question marks, but nothing worked. Is there a way to bind the complete body to the
Body
field in theOptions
struct. I managed to get it working using 2 separate bindings, but I find that less elegant.If it is not possible yet, it might be convenient to add a possibility to do such binding. I use that case frequently during REST API development and I think a lot of people would appreciate such a function too.
Beta Was this translation helpful? Give feedback.
All reactions