forked from hackerzgz/gohessian
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextractor.go
More file actions
121 lines (110 loc) · 2.66 KB
/
extractor.go
File metadata and controls
121 lines (110 loc) · 2.66 KB
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
120
121
package gohessian
import (
"reflect"
log "github.com/cihub/seelog"
)
// extractData help extracting map data into struct
func extractData(data reflect.Value, typ reflect.Type) (rslt reflect.Value) {
rslt = reflect.New(typ)
value := rslt.Elem()
defer func() {
rslt = rslt.Elem()
if r := recover(); r != nil {
log.Debug("Recovered in f", r)
}
log.Trace("rslt: ", rslt)
}()
for value.Kind() == reflect.Ptr {
typ = typ.Elem()
value.Set(reflect.New(typ))
value = value.Elem()
}
for data.Type().Kind() == reflect.Interface ||
(data.Type().Kind() == reflect.Ptr && !reflect.ValueOf(data).IsNil()) {
data = data.Elem()
}
log.Trace("data: ", data.Interface(), ", kind: ", data.Kind())
log.Trace("type: ", typ, ", kind: ", typ.Kind())
switch typ.Kind() {
case reflect.Struct:
if data.Kind() != reflect.Map {
return
}
value.Set(extractStruct(data.Interface(), typ))
case reflect.Slice:
if data.Kind() != reflect.Slice {
return
}
value.Set(extractSlice(data.Interface(), typ))
case reflect.Map:
if data.Kind() != reflect.Map {
return
}
value.Set(extractMap(data.Interface(), typ))
default:
if data.Kind() == reflect.Map {
k := data.MapKeys()[0]
data = data.MapIndex(k)
}
value.Set(data)
}
return
}
func extractStruct(data interface{}, typ reflect.Type) (value reflect.Value) {
if typ.Kind() != reflect.Struct {
return value
}
dataMap := data.(map[interface{}]interface{})
value = reflect.New(typ).Elem()
for i := 0; i < typ.NumField(); i++ {
tf := typ.Field(i)
vf := value.Field(i)
if !vf.CanSet() {
return value
}
if tf.Type.Name() == nameTypeName {
continue // pass hessian name field
}
var name string
var vd interface{}
var ok bool
tag := tf.Tag.Get(hessianTag)
if len(tag) > 0 {
d, ok := dataMap[tag]
if ok {
name = tag
vd = d
}
}
d, ok := dataMap[tf.Name]
if ok {
name = tf.Name
vd = d
}
if len(name) <= 0 || vd == nil {
continue
}
log.Trace("parsing: ", name)
vf.Set(extractData(reflect.ValueOf(vd), tf.Type))
}
return value
}
func extractSlice(data interface{}, typ reflect.Type) (value reflect.Value) {
dataSlice := reflect.ValueOf(data)
value = reflect.MakeSlice(typ, 0, dataSlice.Len())
for i := 0; i < dataSlice.Len(); i++ {
v := extractData(dataSlice.Index(i), typ.Elem())
value = reflect.Append(value, v)
}
return value
}
func extractMap(data interface{}, typ reflect.Type) (value reflect.Value) {
value = reflect.MakeMap(typ)
keys := reflect.ValueOf(data).MapKeys()
for _, kd := range keys {
kv := extractData(kd, typ.Key())
vv := extractData(reflect.ValueOf(data).MapIndex(kd), typ.Elem())
value.SetMapIndex(kv, vv)
}
return value
}