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

Support custom struct tag #2719

Closed
mtt0 opened this issue May 14, 2021 · 0 comments
Closed

Support custom struct tag #2719

mtt0 opened this issue May 14, 2021 · 0 comments

Comments

@mtt0
Copy link
Contributor

mtt0 commented May 14, 2021

Description

Many golang packages have their own struct type and tags, we can not bind their type by binding directly. For example:

go-gitlab use url as struct field tag:
https://github.com/xanzy/go-gitlab/blob/3ce8ea8933fa3f8cdbd0ec1205392417d4ba4701/pipelines.go#L149-L162
so, we can not do this:

func ListHandler(s *Service) func(ctx *gin.Context) {
	return func(ctx *gin.Context) {
		var opt gitlab.ListProjectPipelinesOptions
		// we can't get form data cause missing `form` tag
		err := ctx.BindQuery(&opt)
		if err != nil {
			_ = ctx.Error(err)
			return
		}
		// ...
	}
}

How to solve

  • Add function bind.MapFormWithTag
    form_mapping.go:
func MapFormWithTag(ptr interface{}, form map[string][]string, tag string) error {
	return mapFormByTag(ptr, form, tag)
}

Now we can do this:

const (
	customerTag = "url"
	defaultMemory = 32 << 20
)

type customerBinding struct {}

func (customerBinding) Name() string {
	return "form"
}

func (customerBinding) Bind(req *http.Request, obj interface{}) error {
	if err := req.ParseForm(); err != nil {
		return err
	}
	if err := req.ParseMultipartForm(defaultMemory); err != nil {
		if err != http.ErrNotMultipart {
			return err
		}
	}
	if err := binding.MapFormWithTag(obj, req.Form, customerTag); err != nil {
		return err
	}
	return validate(obj)
}

func validate(obj interface{}) error {
	if binding.Validator == nil {
		return nil
	}
	return binding.Validator.ValidateStruct(obj)
}

// Now we can do this !
func ListHandler(s *Service) func(ctx *gin.Context) {
	return func(ctx *gin.Context) {
                var urlBinding = customerBinding{}
		var opt gitlab.ListProjectPipelinesOptions
		err := ctx.MustBindWith(&opt, urlBinding)
		if err != nil {
			_ = ctx.Error(err)
			return
		}
		// ...
	}
}
mtt0 added a commit to mtt0/gin that referenced this issue May 14, 2021
Add function `binding.MapFormWithTag` (gin-gonic#2719)
mtt0 added a commit to mtt0/gin that referenced this issue May 14, 2021
Add 'Bind form-data request with custom struct and custom tag' section (gin-gonic#2719)
mtt0 added a commit to mtt0/gin that referenced this issue Jun 25, 2021
Add 'Bind form-data request with custom struct and custom tag' section (gin-gonic#2719)
thinkerou pushed a commit that referenced this issue Jun 29, 2021
* feat(binding): support custom struct tag

Add function `binding.MapFormWithTag` (#2719)

* doc: add 'bind form-data with custom struct tag'

Add 'Bind form-data request with custom struct and custom tag' section (#2719)

* test(binding): add test for MapFromWithTag
@mtt0 mtt0 closed this as completed Jul 1, 2021
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