diff options
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.go | 250 |
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 @@ | |||
1 | package jsonutil | ||
2 | |||
3 | import ( | ||
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. | ||
20 | func 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. | ||
38 | func 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 | |||
51 | func 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 | |||
93 | func 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 | |||
141 | func 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 | |||
165 | func 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 | |||
189 | func 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 | } | ||