echo icon indicating copy to clipboard operation
echo copied to clipboard

Binding into a pointer to a slice returns an error "unknown type"

Open maticmeznar opened this issue 3 years ago • 3 comments

Issue Description

When binding input data into a struct with a field with a pointer to a slice, *[]string for example, Bind method returns "unknown type" error.

Checklist

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

Expected behaviour

Successfully bind input data into the provided struct

Actual behaviour

Bind method returns "unknown type" error

Steps to reproduce

package echotest

import (
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

	"github.com/davecgh/go-spew/spew"
	"github.com/labstack/echo/v4"
	"github.com/stretchr/testify/assert"
)

type (
	InputData struct {
		Tags *[]string `json:"tags" query:"tags"`
	}

	handler struct{}
)

func (h *handler) testHandler1(c echo.Context) error {
	data := new(InputData)
	if err := c.Bind(data); err != nil {
		return err
	}

	spew.Dump(data)

	return c.JSON(http.StatusOK, data)
}

func TestTest(t *testing.T) {
	e := echo.New()

	q := make(url.Values)
	q.Add("tags", "testing")
	q.Add("tags", "server")

	req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil)
	// req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)

	h := &handler{}
	if assert.NoError(t, h.testHandler1(c)) {
		assert.Equal(t, http.StatusOK, rec.Code)
	}
}

Version/commit

v4.9.1

maticmeznar avatar Jan 21 '23 19:01 maticmeznar

Changing that field from *[]string to []string should do the trick. At the moment binder knows to only to handle pointers to common types ala string,bool, structs etc and not their slice variants.

InputData struct {
		Tags []string `json:"tags" query:"tags"`
	}

Anyway, I think you are overthinking here with pointers. Unitilialized slice is nil. So if that testcase would have no tags query params this would be after bind:

image

Couple of articles about empty slices:

  • https://medium.com/@habibridho/golang-nil-vs-empty-slice-87fd51c0a4d
  • https://gosamples.dev/empty-vs-nil-slice/

aldas avatar Jan 21 '23 22:01 aldas

Thank you for the reply. The problem is that the struct is automatically generated by oapi-codegen and it creates a pointer unless I set the field as required in the OpenAPI spec.

I was hoping this was a bug since binding into a pointer to a slice works with JSON in the request body.

maticmeznar avatar Jan 22 '23 12:01 maticmeznar

I'll take a look we probably can do something with binder.

for history sake: pointer to slice related issue https://github.com/deepmap/oapi-codegen/issues/266

aldas avatar Jan 23 '23 06:01 aldas