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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
package json
import (
"bytes"
"encoding/json"
"fmt"
"io"
)
// DiscardUnknownField discards unknown fields from a decoder body.
// This function is useful while deserializing a JSON body with additional
// unknown information that should be discarded.
func DiscardUnknownField(decoder *json.Decoder) error {
// This deliberately does not share logic with CollectUnknownField, even
// though it could, because if we were to delegate to that then we'd incur
// extra allocations and general memory usage.
v, err := decoder.Token()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
if _, ok := v.(json.Delim); ok {
for decoder.More() {
err = DiscardUnknownField(decoder)
}
endToken, err := decoder.Token()
if err != nil {
return err
}
if _, ok := endToken.(json.Delim); !ok {
return fmt.Errorf("invalid JSON : expected json delimiter, found %T %v",
endToken, endToken)
}
}
return nil
}
// CollectUnknownField grabs the contents of unknown fields from the decoder body
// and returns them as a byte slice. This is useful for skipping unknown fields without
// completely discarding them.
func CollectUnknownField(decoder *json.Decoder) ([]byte, error) {
result, err := collectUnknownField(decoder)
if err != nil {
return nil, err
}
buff := bytes.NewBuffer(nil)
encoder := json.NewEncoder(buff)
if err := encoder.Encode(result); err != nil {
return nil, err
}
return buff.Bytes(), nil
}
func collectUnknownField(decoder *json.Decoder) (interface{}, error) {
// Grab the initial value. This could either be a concrete value like a string or a a
// delimiter.
token, err := decoder.Token()
if err == io.EOF {
return nil, nil
}
if err != nil {
return nil, err
}
// If it's an array or object, we'll need to recurse.
delim, ok := token.(json.Delim)
if ok {
var result interface{}
if delim == '{' {
result, err = collectUnknownObject(decoder)
if err != nil {
return nil, err
}
} else {
result, err = collectUnknownArray(decoder)
if err != nil {
return nil, err
}
}
// Discard the closing token. decoder.Token handles checking for matching delimiters
if _, err := decoder.Token(); err != nil {
return nil, err
}
return result, nil
}
return token, nil
}
func collectUnknownArray(decoder *json.Decoder) ([]interface{}, error) {
// We need to create an empty array here instead of a nil array, since by getting
// into this function at all we necessarily have seen a non-nil list.
array := []interface{}{}
for decoder.More() {
value, err := collectUnknownField(decoder)
if err != nil {
return nil, err
}
array = append(array, value)
}
return array, nil
}
func collectUnknownObject(decoder *json.Decoder) (map[string]interface{}, error) {
object := make(map[string]interface{})
for decoder.More() {
key, err := collectUnknownField(decoder)
if err != nil {
return nil, err
}
// Keys have to be strings, which is particularly important as the encoder
// won't except a map with interface{} keys
stringKey, ok := key.(string)
if !ok {
return nil, fmt.Errorf("expected string key, found %T", key)
}
value, err := collectUnknownField(decoder)
if err != nil {
return nil, err
}
object[stringKey] = value
}
return object, nil
}
|