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

How can I get map[string]string filed on PostForm? #1362

Closed
syssam opened this issue May 20, 2018 · 22 comments
Closed

How can I get map[string]string filed on PostForm? #1362

syssam opened this issue May 20, 2018 · 22 comments

Comments

@syssam
Copy link
Contributor

syssam commented May 20, 2018

How can I get map[string]string filed on PostForm?

@rstrlcpy
Copy link

Not sure, but maybe something like this

var formDate map[string]string
err := ctx.ShouldBind(&formDate)

@syssam
Copy link
Contributor Author

syssam commented Jun 1, 2018

ShouldBindonly support struct type.

@thinkerou
Copy link
Member

@syssam
Copy link
Contributor Author

syssam commented Jun 5, 2018 via email

@thinkerou
Copy link
Member

please post some example code and why must use map, you also consider to use custom struct, right?

@syssam
Copy link
Contributor Author

syssam commented Jun 5, 2018 via email

@thinkerou
Copy link
Member

@syssam please see #1383

@syssam
Copy link
Contributor Author

syssam commented Jun 6, 2018 via email

@thinkerou
Copy link
Member

thinkerou commented Jun 6, 2018

@syssam Yes, but I think we should not do complex, as far as possible simple. In my option, if you use complex map in query string or post form, maybe you should use custom struct or json.

@delphinus
Copy link

Just idea, how about this to use more flexible?

type QueryString string

// these methods are copied from json.Number 
func (s QueryString) String() string { return string(s) }
func (s QueryString) Float64() (float64, error) {
  return strconv.ParseFloat(string(s), 64)
}
func (s QueryString) Int64() (int64, error) {
  return strconv.ParseInt(string(s), 10, 64)
}

dict := map[string]QueryString

...

and usage

dict := c.QueryMap("ids")
dict["a"].String() // "1234"
dict["a"].Int64()  // 1234, nil

@thinkerou
Copy link
Member

#1383 have supported map parameters for query string and post form.

@syssam
Copy link
Contributor Author

syssam commented Jun 8, 2018

@thinkerou
Copy link
Member

not support form mapping bind now.

@thinkerou
Copy link
Member

@syssam form map bind map #1387

@syssam
Copy link
Contributor Author

syssam commented Jun 10, 2018

@thinkerou Ya.
I'm looking.I'm not test it. however, base on these code, your function will skip, right?

		inputValue, exists := form[inputFieldName]

		if !exists {
			if defaultValue == "" {
				continue
			}
			inputValue = make([]string, 1)
			inputValue[0] = defaultValue
		}

@thinkerou
Copy link
Member

@syssam please read #1387 comment, and you checkout my branch https://github.com/thinkerou/gin/tree/support-map-for-map-form

@syssam
Copy link
Contributor Author

syssam commented Jun 14, 2018

@thinkerou sorry for the late reply.Please make a html form, you will find out the problem.

@thinkerou
Copy link
Member

@syssam your mean is what use text/html header, or use curl .... -d 'a=1&b=2'?

@syssam
Copy link
Contributor Author

syssam commented Jun 15, 2018

Just like

<form>
  <input type="text" name="name[a]"><br>
  <input type="text" name="name[b]">
</form>

@appleboy
Copy link
Member

appleboy commented Aug 6, 2018

Please try the latest version and see the document. https://github.com/gin-gonic/gin#map-as-querystring-or-postform-parameters

@kync
Copy link

kync commented Sep 14, 2018

I was using gorm library to update models using a map(like db.Model(&user).Updates(map[string]interface{}{"uname": "hello", "age": 18, "actived": false})), and needed a bind method that binds request body to a map. I always use a gin context wrapper it has been good practice for me and developed below code and works well for my needs. That would be great if implemented directly in gin. It serves dynamic data binding specially for PUT method.

//AppContext gin context wrapper
type AppContext struct {
	*gin.Context
}
//BindMap decodes body to map, skips fields which are not in allowedFields
func (context AppContext) BindMap(obj map[string]interface{}, allowedFields ...interface{}) error {
	//Provides JSON and Form content types
	if context.Request.Method == "GET" {
		return nil
	}
	contentType := context.ContentType()
	switch contentType {
	case gin.MIMEJSON:
		return context.jsonBind(obj, allowedFields)
	case gin.MIMEPOSTForm, gin.MIMEMultipartPOSTForm:
		return context.formBind(obj, allowedFields)
	default:
		return errors.New("Unsupported content type")
	}
}

//jsonBind binds json into map
func (context AppContext) jsonBind(obj map[string]interface{}, allowedFields ...interface{}) (err error) {
	body, err := ioutil.ReadAll(context.Request.Body)
	if err != nil {
		return err
	}
	return json.Unmarshal(body, &obj)
}

//jsonBind binds form into json
func (context AppContext) formBind(obj map[string]interface{}, allowedFields ...interface{}) (err error) {
	if err = context.Request.ParseForm(); err != nil {
		return err
	}
	context.Request.ParseMultipartForm(defaultMemory)
	for k, v := range context.Request.Form {
		if libs.Contains(k, allowedFields) {
			obj[k] = v[0] //take first
		}
	}
	return nil
}
//Example usage:
//fields := make(map[string]interface{})
//err = appCtx.BindMap(fields, "age", "activated" )

@thinkerou
Copy link
Member

#1749 merged!

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

6 participants