Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mihilbabin committed Feb 1, 2019
1 parent 3805b07 commit 2a282df
Showing 1 changed file with 71 additions and 0 deletions.
71 changes: 71 additions & 0 deletions params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package params

import (
"fmt"
"net/http"
"reflect"
"strconv"
"strings"
)

// Unpack populates the fields of the struct pointed to by ptr
// from the HTTP request parameters in req.
func Unpack(r *http.Request, ptr interface{}) error {
if err := r.ParseForm(); err != nil {
return err
}
fields := make(map[string]reflect.Value)
v := reflect.ValueOf(ptr).Elem()
for i := 0; i < v.NumField(); i++ {
fieldInfo := v.Type().Field(i)
tag := fieldInfo.Tag
name := tag.Get("http")
if name == "" {
name = strings.ToLower(fieldInfo.Name)
}
fields[name] = v.Field(i)
}

for name, values := range r.Form {
f := fields[name]
if !f.IsValid() {
continue
}
for _, value := range values {
if f.Kind() == reflect.Slice {
elem := reflect.New(f.Type().Elem()).Elem()
if err := populate(elem, value); err != nil {
return fmt.Errorf("%s: %v", name, err)
}
f.Set(reflect.Append(f, elem))
} else {
if err := populate(f, value); err != nil {
return fmt.Errorf("%s: %v", name, err)
}
}
}
}
return nil
}

func populate(v reflect.Value, value string) error {
switch v.Kind() {
case reflect.String:
v.SetString(value)
case reflect.Int:
i, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
v.SetInt(i)
case reflect.Bool:
b, err := strconv.ParseBool(value)
if err != nil {
return err
}
v.SetBool(b)
default:
return fmt.Errorf("unsupported kind %s", v.Type())
}
return nil
}

0 comments on commit 2a282df

Please sign in to comment.