-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathunmarshal.go
107 lines (90 loc) · 1.66 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
104
105
106
107
package jsonmap
import (
"bytes"
"encoding/json"
"errors"
)
// UnmarshalJSON implements json.Unmarshaler interface.
// It supports nested maps and arrays.
//
// Note: it does not clear the map before unmarshaling.
// If you want to clear it, call Clear() before UnmarshalJSON().
//
// err := m.UnmarshalJSON([]byte(`{"a":1,"b":2}`))
func (m *Map) UnmarshalJSON(data []byte) error {
d := json.NewDecoder(bytes.NewReader(data))
tok, err := d.Token()
if err != nil {
return err
}
if tok != json.Delim('{') {
return errors.New("expected '{'")
}
return decodeMap(d, m)
}
func decodeMap(d *json.Decoder, m *Map) error {
for {
// key or end
tok, err := d.Token()
if err != nil {
return err
}
if tok == json.Delim('}') {
return nil
}
key, ok := tok.(string)
if !ok {
return errors.New("expected string key")
}
// value
tok, err = d.Token()
if err != nil {
return err
}
switch tok {
case json.Delim('{'):
m2 := New()
err = decodeMap(d, m2)
if err != nil {
return err
}
m.Push(key, m2)
case json.Delim('['):
a, err := decodeArray(d)
if err != nil {
return err
}
m.Push(key, a)
default:
m.Push(key, tok)
}
}
}
func decodeArray(d *json.Decoder) ([]any, error) {
a := make([]any, 0)
for {
tok, err := d.Token()
if err != nil {
return a, err
}
switch tok {
case json.Delim(']'):
return a, nil
case json.Delim('{'):
m := New()
err = decodeMap(d, m)
if err != nil {
return a, err
}
a = append(a, m)
case json.Delim('['):
a2, err := decodeArray(d)
if err != nil {
return a, err
}
a = append(a, a2)
default:
a = append(a, tok)
}
}
}