mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-16 13:22:09 +08:00
feat(json): json support param and query binding
This commit is contained in:
parent
1c48977cca
commit
c65a6b8f25
@ -30,7 +30,7 @@ const (
|
||||
// the form POST.
|
||||
type Binding interface {
|
||||
Name() string
|
||||
Bind(*http.Request, any) error
|
||||
Bind(*http.Request, any, ...Option) error
|
||||
}
|
||||
|
||||
// BindingBody adds BindBody method to Binding. BindBody is similar with Bind,
|
||||
|
@ -19,7 +19,7 @@ func (formBinding) Name() string {
|
||||
return "form"
|
||||
}
|
||||
|
||||
func (formBinding) Bind(req *http.Request, obj any) error {
|
||||
func (formBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -36,7 +36,7 @@ func (formPostBinding) Name() string {
|
||||
return "form-urlencoded"
|
||||
}
|
||||
|
||||
func (formPostBinding) Bind(req *http.Request, obj any) error {
|
||||
func (formPostBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -50,7 +50,7 @@ func (formMultipartBinding) Name() string {
|
||||
return "multipart/form-data"
|
||||
}
|
||||
|
||||
func (formMultipartBinding) Bind(req *http.Request, obj any) error {
|
||||
func (formMultipartBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
if err := req.ParseMultipartForm(defaultMemory); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ func (headerBinding) Name() string {
|
||||
return "header"
|
||||
}
|
||||
|
||||
func (headerBinding) Bind(req *http.Request, obj any) error {
|
||||
func (headerBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
|
||||
if err := mapHeader(obj, req.Header); err != nil {
|
||||
return err
|
||||
|
@ -24,16 +24,37 @@ var EnableDecoderUseNumber = false
|
||||
// keys which do not match any non-ignored, exported fields in the destination.
|
||||
var EnableDecoderDisallowUnknownFields = false
|
||||
|
||||
var EnableParamsAndQueryBinding = false
|
||||
|
||||
type jsonBinding struct{}
|
||||
|
||||
func (jsonBinding) Name() string {
|
||||
return "json"
|
||||
}
|
||||
|
||||
func (jsonBinding) Bind(req *http.Request, obj any) error {
|
||||
func (jsonBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
if req == nil || req.Body == nil {
|
||||
return errors.New("invalid request")
|
||||
}
|
||||
|
||||
if EnableParamsAndQueryBinding {
|
||||
o := &options{}
|
||||
for _, opt := range opts {
|
||||
if err := opt(o); nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if params := o.params; len(params) > 0 {
|
||||
b := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(b).Encode(params); nil != err {
|
||||
return err
|
||||
}
|
||||
if err := decodeJSON(b, obj); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decodeJSON(req.Body, obj)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ func (msgpackBinding) Name() string {
|
||||
return "msgpack"
|
||||
}
|
||||
|
||||
func (msgpackBinding) Bind(req *http.Request, obj any) error {
|
||||
func (msgpackBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
return decodeMsgPack(req.Body, obj)
|
||||
}
|
||||
|
||||
|
15
binding/option.go
Normal file
15
binding/option.go
Normal file
@ -0,0 +1,15 @@
|
||||
package binding
|
||||
|
||||
type options struct {
|
||||
params map[string]interface{}
|
||||
query map[string]interface{}
|
||||
}
|
||||
|
||||
type Option func(opt *options) error
|
||||
|
||||
func WithParams(params map[string]interface{}) Option {
|
||||
return func(opt *options) error {
|
||||
opt.params = params
|
||||
return nil
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ func (protobufBinding) Name() string {
|
||||
return "protobuf"
|
||||
}
|
||||
|
||||
func (b protobufBinding) Bind(req *http.Request, obj any) error {
|
||||
func (b protobufBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
buf, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -12,7 +12,7 @@ func (queryBinding) Name() string {
|
||||
return "query"
|
||||
}
|
||||
|
||||
func (queryBinding) Bind(req *http.Request, obj any) error {
|
||||
func (queryBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
values := req.URL.Query()
|
||||
if err := mapForm(obj, values); err != nil {
|
||||
return err
|
||||
|
@ -26,7 +26,7 @@ func decodeToml(r io.Reader, obj any) error {
|
||||
return decoder.Decode(obj)
|
||||
}
|
||||
|
||||
func (tomlBinding) Bind(req *http.Request, obj any) error {
|
||||
func (tomlBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
return decodeToml(req.Body, obj)
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ func (xmlBinding) Name() string {
|
||||
return "xml"
|
||||
}
|
||||
|
||||
func (xmlBinding) Bind(req *http.Request, obj any) error {
|
||||
func (xmlBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
return decodeXML(req.Body, obj)
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ func (yamlBinding) Name() string {
|
||||
return "yaml"
|
||||
}
|
||||
|
||||
func (yamlBinding) Bind(req *http.Request, obj any) error {
|
||||
func (yamlBinding) Bind(req *http.Request, obj any, opts ...Option) error {
|
||||
return decodeYAML(req.Body, obj)
|
||||
}
|
||||
|
||||
|
15
context.go
15
context.go
@ -732,7 +732,20 @@ func (c *Context) ShouldBindUri(obj any) error {
|
||||
// ShouldBindWith binds the passed struct pointer using the specified binding engine.
|
||||
// See the binding package.
|
||||
func (c *Context) ShouldBindWith(obj any, b binding.Binding) error {
|
||||
return b.Bind(c.Request, obj)
|
||||
return b.Bind(c.Request, obj, binding.WithParams(func() (ret map[string]interface{}) {
|
||||
ret = make(map[string]interface{})
|
||||
for _, item := range c.Params {
|
||||
ret[item.Key] = item.Value
|
||||
}
|
||||
for key, val := range c.Request.URL.Query() {
|
||||
if len(val) == 1 {
|
||||
ret[key] = val[0]
|
||||
continue
|
||||
}
|
||||
ret[key] = val
|
||||
}
|
||||
return
|
||||
}()))
|
||||
}
|
||||
|
||||
// ShouldBindBodyWith is similar with ShouldBindWith, but it stores the request
|
||||
|
Loading…
x
Reference in New Issue
Block a user