f5523388 by miraclesu

Add ParseForm function

1 parent 23deaedd
...@@ -4,7 +4,10 @@ import ( ...@@ -4,7 +4,10 @@ import (
4 "fmt" 4 "fmt"
5 "github.com/russross/blackfriday" 5 "github.com/russross/blackfriday"
6 "html/template" 6 "html/template"
7 "net/url"
8 "reflect"
7 "regexp" 9 "regexp"
10 "strconv"
8 "strings" 11 "strings"
9 "time" 12 "time"
10 ) 13 )
...@@ -179,3 +182,80 @@ func inSlice(v string, sl []string) bool { ...@@ -179,3 +182,80 @@ func inSlice(v string, sl []string) bool {
179 } 182 }
180 return false 183 return false
181 } 184 }
185
186 // parse form values to struct via tag
187 func ParseForm(form url.Values, obj interface{}) error {
188 objT := reflect.TypeOf(obj)
189 objV := reflect.ValueOf(obj)
190 if !(objT.Kind() == reflect.Ptr && objT.Elem().Kind() == reflect.Struct) {
191 return fmt.Errorf("%v must be a struct pointer", obj)
192 }
193 objT = objT.Elem()
194 objV = objV.Elem()
195
196 for i := 0; i < objT.NumField(); i++ {
197 fieldV := objV.Field(i)
198 if !fieldV.CanSet() {
199 continue
200 }
201 fieldT := objT.Field(i)
202 tag := fieldT.Tag.Get("form")
203 if len(tag) == 0 {
204 tag = fieldT.Name
205 }
206 value := form.Get(tag)
207 if len(value) == 0 {
208 continue
209 }
210
211 switch fieldT.Type.Kind() {
212 case reflect.Bool:
213 b, err := strconv.ParseBool(value)
214 if err != nil {
215 return err
216 }
217 fieldV.SetBool(b)
218 case reflect.Int:
219 fallthrough
220 case reflect.Int8:
221 fallthrough
222 case reflect.Int16:
223 fallthrough
224 case reflect.Int32:
225 fallthrough
226 case reflect.Int64:
227 x, err := strconv.ParseInt(value, 10, 64)
228 if err != nil {
229 return err
230 }
231 fieldV.SetInt(x)
232 case reflect.Uint:
233 fallthrough
234 case reflect.Uint8:
235 fallthrough
236 case reflect.Uint16:
237 fallthrough
238 case reflect.Uint32:
239 fallthrough
240 case reflect.Uint64:
241 x, err := strconv.ParseUint(value, 10, 64)
242 if err != nil {
243 return err
244 }
245 fieldV.SetUint(x)
246 case reflect.Float32:
247 fallthrough
248 case reflect.Float64:
249 x, err := strconv.ParseFloat(value, 64)
250 if err != nil {
251 return err
252 }
253 fieldV.SetFloat(x)
254 case reflect.Interface:
255 fieldV.Set(reflect.ValueOf(value))
256 case reflect.String:
257 fieldV.SetString(value)
258 }
259 }
260 return nil
261 }
......
1 package beego
2
3 import (
4 "net/url"
5 "testing"
6 )
7
8 func TestParseForm(t *testing.T) {
9 type user struct {
10 Id int
11 tag string `form:tag`
12 Name interface{} `form:"username"`
13 Age int `form:"age"`
14 Email string
15 }
16
17 u := user{}
18 form := url.Values{
19 "tag": []string{"no"},
20 "username": []string{"test"},
21 "age": []string{"40"},
22 "Email": []string{"test@gmail.com"},
23 }
24 if err := ParseForm(form, u); err == nil {
25 t.Fatal("nothing will be changed")
26 }
27 if err := ParseForm(form, &u); err != nil {
28 t.Fatal(err)
29 }
30 if u.Name.(string) != "test" {
31 t.Error("should be equal")
32 }
33 if u.Age != 40 {
34 t.Error("should be equal")
35 }
36 if u.Email != "test@gmail.com" {
37 t.Error("should be equal")
38 }
39 }
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!