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
DataPointobjects, I want to bind them to theBodyfield 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
Bodyfield in theOptionsstruct. 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