Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encode and Decode custom type function, we can get match reflect.Type in callback! #65

Open
thinkgos opened this issue May 29, 2024 · 0 comments

Comments

@thinkgos
Copy link

thinkgos commented May 29, 2024

Package version eg. v4:

Issue, Question or Enhancement:

DecodeCustomTypeFunc should be not func([]string) (interface{}, error), may be func(reflect.Type,[]string) (interface{}, error) will be better.
also. EncodeCustomTypeFunc: func(x interface{}) ([]string, error) -> func(t reflect.Type, x interface{}) ([]string, error).

get the match reflect.Type. the custom type parse function can do more thing.

Code sample, to showcase or reproduce:

example below:

I want to parser id=1,2,3 to []int or []CustomInt or more.

type CustomInt int

func DecodeCustomIntSlice[T ~int](values []string) (any, error) {
	if len(values) == 0 {
		return []T{}, nil
	}
	// FIXME: make slice space
	ret := make([]T, 0)
	for _, s := range values {
		for _, v := range strings.Split(s, ",") {
			i, err := strconv.ParseInt(v, 10, 0)
			if err != nil {
				return nil, err
			}
			ret = append(ret, T(i))
		}
	}
	return ret, nil
}
dec := form.NewDecoder()
dec.SetTagName("json")
dec.RegisterCustomTypeFunc(DecodeCustomIntSlice[int], []int{})
dec.RegisterCustomTypeFunc(DecodeCustomIntSlice[CustomInt], []CustomInt{})

I have to register twice. if decoder.go#L191 pass the reflect.Type to custom type parser function, we can register in one line.

if DecodeCustomTypeFunc is func(reflect.Type,[]string) (interface{}, error), we can simple do below:

type CustomInt int
type CustomInt1 int
type CustomInt2 int

func DecodeCommaStringToSlice(t reflect.Type, values []string) (any, error) {
	if t.Kind() != reflect.Slice {
		return nil, &form.InvalidDecoderError{Type: t}
	}
	ret := reflect.MakeSlice(t, 0, 0)
	te := t.Elem()
	teKind := te.Kind()
	for _, s := range values {
		for _, ss := range strings.Split(s, ",") {
			switch teKind {
			case reflect.Int:
				i, err := strconv.ParseInt(ss, 10, 0)
				if err != nil {
					return nil, err
				}
				val := reflect.New(te).Elem()
				val.SetInt(i)
				ret = reflect.Append(ret, val)
			}
		}
	}
	return ret.Interface(), nil
}

dec := form.NewDecoder()
dec.SetTagName("json")
dec.RegisterCustomTypeFunc(DecodeCommaStringToSlice, []int{},[]CustomInt{},[]CustomInt1{},[]CustomInt2{})

Is there any other better solution?

@thinkgos thinkgos reopened this May 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant