-
Notifications
You must be signed in to change notification settings - Fork 15
/
codec_json_safe.go
108 lines (88 loc) · 2.65 KB
/
codec_json_safe.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
package dingo
import (
"encoding/json"
"fmt"
"reflect"
)
/*
Different from JsonMarshaller, which marshal []interface{} to a single byte stream.
JSONSafeCodec would marshal each element in []interface{} to separated byte steam,
and unmarshall them to variable with "more accurated" type.
Note: this Codec can be used with GenericInvoker and LazyInvoker
*/
type JSONSafeCodec struct{}
func (codec *JSONSafeCodec) Prepare(name string, fn interface{}) (err error) {
return
}
func (codec *JSONSafeCodec) EncodeArgument(fn interface{}, val []interface{}) ([][]byte, error) {
if len(val) != reflect.TypeOf(fn).NumIn() {
return nil, fmt.Errorf("Unable to encode %v, because its count of args is wrong", fn)
}
return codec.encode(val)
}
func (codec *JSONSafeCodec) DecodeArgument(fn interface{}, bs [][]byte) ([]interface{}, error) {
funcT := reflect.TypeOf(fn)
if len(bs) != funcT.NumIn() {
return nil, fmt.Errorf("Unable to decode %v, because its count of args is wrong", fn)
}
return codec.decode(bs, func(i int) reflect.Type {
return funcT.In(i)
})
}
func (codec *JSONSafeCodec) EncodeReturn(fn interface{}, val []interface{}) ([][]byte, error) {
if len(val) != reflect.TypeOf(fn).NumOut() {
return nil, fmt.Errorf("Unable to encode %v, because its count of args is wrong", fn)
}
return codec.encode(val)
}
func (codec *JSONSafeCodec) DecodeReturn(fn interface{}, bs [][]byte) ([]interface{}, error) {
funcT := reflect.TypeOf(fn)
if len(bs) != funcT.NumOut() {
return nil, fmt.Errorf("Unable to decode %v, because its count of args is wrong", fn)
}
return codec.decode(bs, func(i int) reflect.Type {
return funcT.Out(i)
})
}
func (codec *JSONSafeCodec) encode(vs []interface{}) (bs [][]byte, err error) {
bs = make([][]byte, 0, len(vs))
for _, v := range vs {
var b []byte
b, err = json.Marshal(v)
if err != nil {
return
}
bs = append(bs, b)
}
return
}
func (codec *JSONSafeCodec) decode(bs [][]byte, tfn func(i int) reflect.Type) ([]interface{}, error) {
vs := make([]interface{}, 0, len(bs))
for k, b := range bs {
t := tfn(k)
v := reflect.New(t)
r := v.Elem() // cache the value for the right type
if r.CanInterface() == false {
return nil, fmt.Errorf("can't interface of r %d:%v", k, t)
}
if t.Kind() != reflect.Ptr {
// inputs for json.Unmarshal can't be nil
v.Elem().Set(reflect.New(t).Elem())
} else {
for t.Kind() == reflect.Ptr {
t = t.Elem()
if t.Kind() == reflect.Ptr {
v.Elem().Set(reflect.New(t))
v = v.Elem()
}
}
}
// generate a zero value
err := json.Unmarshal(b, v.Interface())
if err != nil {
return nil, err
}
vs = append(vs, r.Interface())
}
return vs, nil
}