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
Uh oh!
There was an error while loading. Please reload this page.
-
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