-
Notifications
You must be signed in to change notification settings - Fork 146
/
map2struct.go
119 lines (113 loc) · 2.35 KB
/
map2struct.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package gor
import (
"fmt"
"log"
"reflect"
"strconv"
"strings"
"time"
)
// 将map赋值到一个struct
func ToStruct(m map[string]interface{}, val reflect.Value) {
if m == nil {
return
}
if val.Kind() == reflect.Ptr && val.Elem().Kind() != reflect.Struct {
log.Println("ERR, 仅支持*struct")
return
}
origin_val := val
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
for k, v := range m {
field := val.FieldByName(strings.Title(k))
if !field.IsValid() {
continue
}
if !field.CanSet() {
log.Println("CanSet = false", k, v)
continue
}
//D("Found key=", k, "value=", v, field.Type().String())
switch field.Kind() {
case reflect.String:
//log.Println("Ready to SetString", v)
if _str, ok := v.(string); ok {
field.SetString(_str)
} else {
field.SetString(fmt.Sprint("%v", v))
}
case reflect.Int:
fallthrough
case reflect.Int64:
field.SetInt(ToInt64(v, 0))
case reflect.Slice: // 字段总是slice
if _strs, ok := v.([]string); ok {
field.Set(reflect.ValueOf(_strs))
} else if _slice, ok := v.([]interface{}); ok {
strs := make([]string, len(_slice))
for i, vz := range _slice {
strs[i] = vz.(string)
}
field.Set(reflect.ValueOf(strs))
} else {
log.Println("Only []string is supported yet")
}
case reflect.Map:
field.Set(reflect.ValueOf(v))
case reflect.Ptr:
// No support yet
case reflect.Struct:
if field.Type().String() == "time.Time" {
if t, ok := v.(time.Time); ok {
field.Set(reflect.ValueOf(t))
break
}
}
v2, ok := v.(map[string]interface{})
if !ok {
log.Println("Not a map[string]interface{}", "key=", k, "value=", v)
return
}
ToStruct(v2, field)
default:
field.Set(reflect.ValueOf(v))
}
}
_ = origin_val
}
func ToInt(v interface{}, defaultValue int) int {
if v == nil {
return defaultValue
}
if i, ok := v.(int); ok {
return i
}
if i2, ok := v.(int64); ok {
return int(i2)
}
str := fmt.Sprintf("%v", v)
i, err := strconv.Atoi(str)
if err != nil {
return defaultValue
}
return i
}
func ToInt64(v interface{}, defaultValue int64) int64 {
if v == nil {
return defaultValue
}
if i, ok := v.(int64); ok {
return i
}
if i2, ok := v.(int); ok {
return int64(i2)
}
str := fmt.Sprintf("%v", v)
i, err := strconv.ParseInt(str, 0, 64)
if err != nil {
return defaultValue
}
return i
}