aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go')
-rw-r--r--vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go250
1 files changed, 250 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
new file mode 100644
index 0000000..ea0da79
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
@@ -0,0 +1,250 @@
1package jsonutil
2
3import (
4 "bytes"
5 "encoding/base64"
6 "encoding/json"
7 "fmt"
8 "io"
9 "reflect"
10 "time"
11
12 "github.com/aws/aws-sdk-go/aws"
13 "github.com/aws/aws-sdk-go/aws/awserr"
14 "github.com/aws/aws-sdk-go/private/protocol"
15)
16
17// UnmarshalJSONError unmarshal's the reader's JSON document into the passed in
18// type. The value to unmarshal the json document into must be a pointer to the
19// type.
20func UnmarshalJSONError(v interface{}, stream io.Reader) error {
21 var errBuf bytes.Buffer
22 body := io.TeeReader(stream, &errBuf)
23
24 err := json.NewDecoder(body).Decode(v)
25 if err != nil {
26 msg := "failed decoding error message"
27 if err == io.EOF {
28 msg = "error message missing"
29 err = nil
30 }
31 return awserr.NewUnmarshalError(err, msg, errBuf.Bytes())
32 }
33
34 return nil
35}
36
37// UnmarshalJSON reads a stream and unmarshals the results in object v.
38func UnmarshalJSON(v interface{}, stream io.Reader) error {
39 var out interface{}
40
41 err := json.NewDecoder(stream).Decode(&out)
42 if err == io.EOF {
43 return nil
44 } else if err != nil {
45 return err
46 }
47
48 return unmarshalAny(reflect.ValueOf(v), out, "")
49}
50
51func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error {
52 vtype := value.Type()
53 if vtype.Kind() == reflect.Ptr {
54 vtype = vtype.Elem() // check kind of actual element type
55 }
56
57 t := tag.Get("type")
58 if t == "" {
59 switch vtype.Kind() {
60 case reflect.Struct:
61 // also it can't be a time object
62 if _, ok := value.Interface().(*time.Time); !ok {
63 t = "structure"
64 }
65 case reflect.Slice:
66 // also it can't be a byte slice
67 if _, ok := value.Interface().([]byte); !ok {
68 t = "list"
69 }
70 case reflect.Map:
71 // cannot be a JSONValue map
72 if _, ok := value.Interface().(aws.JSONValue); !ok {
73 t = "map"
74 }
75 }
76 }
77
78 switch t {
79 case "structure":
80 if field, ok := vtype.FieldByName("_"); ok {
81 tag = field.Tag
82 }
83 return unmarshalStruct(value, data, tag)
84 case "list":
85 return unmarshalList(value, data, tag)
86 case "map":
87 return unmarshalMap(value, data, tag)
88 default:
89 return unmarshalScalar(value, data, tag)
90 }
91}
92
93func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error {
94 if data == nil {
95 return nil
96 }
97 mapData, ok := data.(map[string]interface{})
98 if !ok {
99 return fmt.Errorf("JSON value is not a structure (%#v)", data)
100 }
101
102 t := value.Type()
103 if value.Kind() == reflect.Ptr {
104 if value.IsNil() { // create the structure if it's nil
105 s := reflect.New(value.Type().Elem())
106 value.Set(s)
107 value = s
108 }
109
110 value = value.Elem()
111 t = t.Elem()
112 }
113
114 // unwrap any payloads
115 if payload := tag.Get("payload"); payload != "" {
116 field, _ := t.FieldByName(payload)
117 return unmarshalAny(value.FieldByName(payload), data, field.Tag)
118 }
119
120 for i := 0; i < t.NumField(); i++ {
121 field := t.Field(i)
122 if field.PkgPath != "" {
123 continue // ignore unexported fields
124 }
125
126 // figure out what this field is called
127 name := field.Name
128 if locName := field.Tag.Get("locationName"); locName != "" {
129 name = locName
130 }
131
132 member := value.FieldByIndex(field.Index)
133 err := unmarshalAny(member, mapData[name], field.Tag)
134 if err != nil {
135 return err
136 }
137 }
138 return nil
139}
140
141func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error {
142 if data == nil {
143 return nil
144 }
145 listData, ok := data.([]interface{})
146 if !ok {
147 return fmt.Errorf("JSON value is not a list (%#v)", data)
148 }
149
150 if value.IsNil() {
151 l := len(listData)
152 value.Set(reflect.MakeSlice(value.Type(), l, l))
153 }
154
155 for i, c := range listData {
156 err := unmarshalAny(value.Index(i), c, "")
157 if err != nil {
158 return err
159 }
160 }
161
162 return nil
163}
164
165func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error {
166 if data == nil {
167 return nil
168 }
169 mapData, ok := data.(map[string]interface{})
170 if !ok {
171 return fmt.Errorf("JSON value is not a map (%#v)", data)
172 }
173
174 if value.IsNil() {
175 value.Set(reflect.MakeMap(value.Type()))
176 }
177
178 for k, v := range mapData {
179 kvalue := reflect.ValueOf(k)
180 vvalue := reflect.New(value.Type().Elem()).Elem()
181
182 unmarshalAny(vvalue, v, "")
183 value.SetMapIndex(kvalue, vvalue)
184 }
185
186 return nil
187}
188
189func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error {
190
191 switch d := data.(type) {
192 case nil:
193 return nil // nothing to do here
194 case string:
195 switch value.Interface().(type) {
196 case *string:
197 value.Set(reflect.ValueOf(&d))
198 case []byte:
199 b, err := base64.StdEncoding.DecodeString(d)
200 if err != nil {
201 return err
202 }
203 value.Set(reflect.ValueOf(b))
204 case *time.Time:
205 format := tag.Get("timestampFormat")
206 if len(format) == 0 {
207 format = protocol.ISO8601TimeFormatName
208 }
209
210 t, err := protocol.ParseTime(format, d)
211 if err != nil {
212 return err
213 }
214 value.Set(reflect.ValueOf(&t))
215 case aws.JSONValue:
216 // No need to use escaping as the value is a non-quoted string.
217 v, err := protocol.DecodeJSONValue(d, protocol.NoEscape)
218 if err != nil {
219 return err
220 }
221 value.Set(reflect.ValueOf(v))
222 default:
223 return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
224 }
225 case float64:
226 switch value.Interface().(type) {
227 case *int64:
228 di := int64(d)
229 value.Set(reflect.ValueOf(&di))
230 case *float64:
231 value.Set(reflect.ValueOf(&d))
232 case *time.Time:
233 // Time unmarshaled from a float64 can only be epoch seconds
234 t := time.Unix(int64(d), 0).UTC()
235 value.Set(reflect.ValueOf(&t))
236 default:
237 return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
238 }
239 case bool:
240 switch value.Interface().(type) {
241 case *bool:
242 value.Set(reflect.ValueOf(&d))
243 default:
244 return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
245 }
246 default:
247 return fmt.Errorf("unsupported JSON value (%v)", data)
248 }
249 return nil
250}