-
Notifications
You must be signed in to change notification settings - Fork 50
/
unmarshal.go
103 lines (77 loc) · 2.3 KB
/
unmarshal.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
package ddb
import (
"fmt"
"reflect"
"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)
type Unmarshaller struct {
result reflect.Value
typ reflect.Type
}
func NewUnmarshallerFromPtrSlice(result interface{}) (*Unmarshaller, error) {
ptr := reflect.ValueOf(result)
if ptr.Kind() != reflect.Ptr {
return nil, fmt.Errorf("result interface is not a pointer")
}
value := ptr.Elem()
if value.Kind() != reflect.Slice {
return nil, fmt.Errorf("result interface is not a slice")
}
um := &Unmarshaller{
result: value,
typ: value.Type(),
}
return um, nil
}
func NewUnmarshallerFromStruct(model interface{}) (*Unmarshaller, error) {
elemType := reflect.TypeOf(model)
elemSlice := reflect.MakeSlice(reflect.SliceOf(elemType), 0, 10)
um := &Unmarshaller{
result: elemSlice,
typ: elemSlice.Type(),
}
return um, nil
}
func (u *Unmarshaller) Unmarshal(items []map[string]types.AttributeValue) (interface{}, error) {
partValue := reflect.New(u.typ)
part := partValue.Interface()
err := UnmarshalListOfMaps(items, &part)
if err != nil {
return nil, err
}
indirect := reflect.Indirect(partValue)
result := indirect.Interface()
return result, nil
}
func (u *Unmarshaller) Append(items []map[string]types.AttributeValue) error {
partValue := reflect.New(u.typ)
part := partValue.Interface()
indirect := reflect.Indirect(partValue)
err := UnmarshalListOfMaps(items, &part)
if err != nil {
return err
}
for i := 0; i < indirect.Len(); i++ {
u.result.Set(reflect.Append(u.result, indirect.Index(i)))
}
return nil
}
func NewDecoder() *attributevalue.Decoder {
return attributevalue.NewDecoder(func(options *attributevalue.DecoderOptions) {
options.TagKey = "json"
})
}
func UnmarshalListOfMaps(l []map[string]types.AttributeValue, out interface{}) error {
items := make([]types.AttributeValue, len(l))
for i, m := range l {
items[i] = &types.AttributeValueMemberM{Value: m}
}
return UnmarshalList(items, out)
}
func UnmarshalList(l []types.AttributeValue, out interface{}) error {
return NewDecoder().Decode(&types.AttributeValueMemberL{Value: l}, out)
}
func UnmarshalMap(m map[string]types.AttributeValue, out interface{}) error {
return NewDecoder().Decode(&types.AttributeValueMemberM{Value: m}, out)
}