1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT license.
3
4package json
5
6import (
7 "encoding/json"
8 "fmt"
9 "reflect"
10)
11
12// unmarshalMap unmarshal's a map.
13func unmarshalMap(dec *json.Decoder, m reflect.Value) error {
14 if m.Kind() != reflect.Ptr || m.Elem().Kind() != reflect.Map {
15 panic("unmarshalMap called on non-*map value")
16 }
17 mapValueType := m.Elem().Type().Elem()
18 walk := mapWalk{dec: dec, m: m, valueType: mapValueType}
19 if err := walk.run(); err != nil {
20 return err
21 }
22 return nil
23}
24
25type mapWalk struct {
26 dec *json.Decoder
27 key string
28 m reflect.Value
29 valueType reflect.Type
30}
31
32// run runs our decoder state machine.
33func (m *mapWalk) run() error {
34 var state = m.start
35 var err error
36 for {
37 state, err = state()
38 if err != nil {
39 return err
40 }
41 if state == nil {
42 return nil
43 }
44 }
45}
46
47func (m *mapWalk) start() (stateFn, error) {
48 // maps can have custom unmarshaler's.
49 if hasUnmarshalJSON(m.m) {
50 err := m.dec.Decode(m.m.Interface())
51 if err != nil {
52 return nil, err
53 }
54 return nil, nil
55 }
56
57 // We only want to use this if the map value is:
58 // *struct/struct/map/slice
59 // otherwise use standard decode
60 t, _ := m.valueBaseType()
61 switch t.Kind() {
62 case reflect.Struct, reflect.Map, reflect.Slice:
63 delim, err := m.dec.Token()
64 if err != nil {
65 return nil, err
66 }
67 // This indicates the value was set to JSON null.
68 if delim == nil {
69 return nil, nil
70 }
71 if !delimIs(delim, '{') {
72 return nil, fmt.Errorf("Unmarshal expected opening {, received %v", delim)
73 }
74 return m.next, nil
75 case reflect.Ptr:
76 return nil, fmt.Errorf("do not support maps with values of '**type' or '*reference")
77 }
78
79 // This is a basic map type, so just use Decode().
80 if err := m.dec.Decode(m.m.Interface()); err != nil {
81 return nil, err
82 }
83
84 return nil, nil
85}
86
87func (m *mapWalk) next() (stateFn, error) {
88 if m.dec.More() {
89 key, err := m.dec.Token()
90 if err != nil {
91 return nil, err
92 }
93 m.key = key.(string)
94 return m.storeValue, nil
95 }
96 // No more entries, so remove final }.
97 _, err := m.dec.Token()
98 if err != nil {
99 return nil, err
100 }
101 return nil, nil
102}
103
104func (m *mapWalk) storeValue() (stateFn, error) {
105 v := m.valueType
106 for {
107 switch v.Kind() {
108 case reflect.Ptr:
109 v = v.Elem()
110 continue
111 case reflect.Struct:
112 return m.storeStruct, nil
113 case reflect.Map:
114 return m.storeMap, nil
115 case reflect.Slice:
116 return m.storeSlice, nil
117 }
118 return nil, fmt.Errorf("bug: mapWalk.storeValue() called on unsupported type: %v", v.Kind())
119 }
120}
121
122func (m *mapWalk) storeStruct() (stateFn, error) {
123 v := newValue(m.valueType)
124 if err := unmarshalStruct(m.dec, v.Interface()); err != nil {
125 return nil, err
126 }
127
128 if m.valueType.Kind() == reflect.Ptr {
129 m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v)
130 return m.next, nil
131 }
132 m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v.Elem())
133
134 return m.next, nil
135}
136
137func (m *mapWalk) storeMap() (stateFn, error) {
138 v := reflect.MakeMap(m.valueType)
139 ptr := newValue(v.Type())
140 ptr.Elem().Set(v)
141 if err := unmarshalMap(m.dec, ptr); err != nil {
142 return nil, err
143 }
144
145 m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v)
146
147 return m.next, nil
148}
149
150func (m *mapWalk) storeSlice() (stateFn, error) {
151 v := newValue(m.valueType)
152 if err := unmarshalSlice(m.dec, v); err != nil {
153 return nil, err
154 }
155
156 m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v.Elem())
157
158 return m.next, nil
159}
160
161// valueType returns the underlying Type. So a *struct would yield
162// struct, etc...
163func (m *mapWalk) valueBaseType() (reflect.Type, bool) {
164 ptr := false
165 v := m.valueType
166 if v.Kind() == reflect.Ptr {
167 ptr = true
168 v = v.Elem()
169 }
170 return v, ptr
171}
172
173// unmarshalSlice unmarshal's the next value, which must be a slice, into
174// ptrSlice, which must be a pointer to a slice. newValue() can be use to
175// create the slice.
176func unmarshalSlice(dec *json.Decoder, ptrSlice reflect.Value) error {
177 if ptrSlice.Kind() != reflect.Ptr || ptrSlice.Elem().Kind() != reflect.Slice {
178 panic("unmarshalSlice called on non-*[]slice value")
179 }
180 sliceValueType := ptrSlice.Elem().Type().Elem()
181 walk := sliceWalk{
182 dec: dec,
183 s: ptrSlice,
184 valueType: sliceValueType,
185 }
186 if err := walk.run(); err != nil {
187 return err
188 }
189
190 return nil
191}
192
193type sliceWalk struct {
194 dec *json.Decoder
195 s reflect.Value // *[]slice
196 valueType reflect.Type
197}
198
199// run runs our decoder state machine.
200func (s *sliceWalk) run() error {
201 var state = s.start
202 var err error
203 for {
204 state, err = state()
205 if err != nil {
206 return err
207 }
208 if state == nil {
209 return nil
210 }
211 }
212}
213
214func (s *sliceWalk) start() (stateFn, error) {
215 // slices can have custom unmarshaler's.
216 if hasUnmarshalJSON(s.s) {
217 err := s.dec.Decode(s.s.Interface())
218 if err != nil {
219 return nil, err
220 }
221 return nil, nil
222 }
223
224 // We only want to use this if the slice value is:
225 // []*struct/[]struct/[]map/[]slice
226 // otherwise use standard decode
227 t := s.valueBaseType()
228
229 switch t.Kind() {
230 case reflect.Ptr:
231 return nil, fmt.Errorf("cannot unmarshal into a **<type> or *<reference>")
232 case reflect.Struct, reflect.Map, reflect.Slice:
233 delim, err := s.dec.Token()
234 if err != nil {
235 return nil, err
236 }
237 // This indicates the value was set to nil.
238 if delim == nil {
239 return nil, nil
240 }
241 if !delimIs(delim, '[') {
242 return nil, fmt.Errorf("Unmarshal expected opening [, received %v", delim)
243 }
244 return s.next, nil
245 }
246
247 if err := s.dec.Decode(s.s.Interface()); err != nil {
248 return nil, err
249 }
250 return nil, nil
251}
252
253func (s *sliceWalk) next() (stateFn, error) {
254 if s.dec.More() {
255 return s.storeValue, nil
256 }
257 // Nothing left in the slice, remove closing ]
258 _, err := s.dec.Token()
259 return nil, err
260}
261
262func (s *sliceWalk) storeValue() (stateFn, error) {
263 t := s.valueBaseType()
264 switch t.Kind() {
265 case reflect.Ptr:
266 return nil, fmt.Errorf("do not support 'pointer to pointer' or 'pointer to reference' types")
267 case reflect.Struct:
268 return s.storeStruct, nil
269 case reflect.Map:
270 return s.storeMap, nil
271 case reflect.Slice:
272 return s.storeSlice, nil
273 }
274 return nil, fmt.Errorf("bug: sliceWalk.storeValue() called on unsupported type: %v", t.Kind())
275}
276
277func (s *sliceWalk) storeStruct() (stateFn, error) {
278 v := newValue(s.valueType)
279 if err := unmarshalStruct(s.dec, v.Interface()); err != nil {
280 return nil, err
281 }
282
283 if s.valueType.Kind() == reflect.Ptr {
284 s.s.Elem().Set(reflect.Append(s.s.Elem(), v))
285 return s.next, nil
286 }
287
288 s.s.Elem().Set(reflect.Append(s.s.Elem(), v.Elem()))
289 return s.next, nil
290}
291
292func (s *sliceWalk) storeMap() (stateFn, error) {
293 v := reflect.MakeMap(s.valueType)
294 ptr := newValue(v.Type())
295 ptr.Elem().Set(v)
296
297 if err := unmarshalMap(s.dec, ptr); err != nil {
298 return nil, err
299 }
300
301 s.s.Elem().Set(reflect.Append(s.s.Elem(), v))
302
303 return s.next, nil
304}
305
306func (s *sliceWalk) storeSlice() (stateFn, error) {
307 v := newValue(s.valueType)
308 if err := unmarshalSlice(s.dec, v); err != nil {
309 return nil, err
310 }
311
312 s.s.Elem().Set(reflect.Append(s.s.Elem(), v.Elem()))
313
314 return s.next, nil
315}
316
317// valueType returns the underlying Type. So a *struct would yield
318// struct, etc...
319func (s *sliceWalk) valueBaseType() reflect.Type {
320 v := s.valueType
321 if v.Kind() == reflect.Ptr {
322 v = v.Elem()
323 }
324 return v
325}
326
327// newValue() returns a new *type that represents type passed.
328func newValue(valueType reflect.Type) reflect.Value {
329 if valueType.Kind() == reflect.Ptr {
330 return reflect.New(valueType.Elem())
331 }
332 return reflect.New(valueType)
333}