1 package extra
2
3 import (
4 "encoding/json"
5 "io"
6 "math"
7 "reflect"
8 "strings"
9 "unsafe"
10
11 "github.com/json-iterator/go"
12 "github.com/modern-go/reflect2"
13 )
14
15 const maxUint = ^uint(0)
16 const maxInt = int(maxUint >> 1)
17 const minInt = -maxInt - 1
18
19
20
21 func RegisterFuzzyDecoders() {
22 jsoniter.RegisterExtension(&tolerateEmptyArrayExtension{})
23 jsoniter.RegisterTypeDecoder("string", &fuzzyStringDecoder{})
24 jsoniter.RegisterTypeDecoder("float32", &fuzzyFloat32Decoder{})
25 jsoniter.RegisterTypeDecoder("float64", &fuzzyFloat64Decoder{})
26 jsoniter.RegisterTypeDecoder("int", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
27 if isFloat {
28 val := iter.ReadFloat64()
29 if val > float64(maxInt) || val < float64(minInt) {
30 iter.ReportError("fuzzy decode int", "exceed range")
31 return
32 }
33 *((*int)(ptr)) = int(val)
34 } else {
35 *((*int)(ptr)) = iter.ReadInt()
36 }
37 }})
38 jsoniter.RegisterTypeDecoder("uint", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
39 if isFloat {
40 val := iter.ReadFloat64()
41 if val > float64(maxUint) || val < 0 {
42 iter.ReportError("fuzzy decode uint", "exceed range")
43 return
44 }
45 *((*uint)(ptr)) = uint(val)
46 } else {
47 *((*uint)(ptr)) = iter.ReadUint()
48 }
49 }})
50 jsoniter.RegisterTypeDecoder("int8", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
51 if isFloat {
52 val := iter.ReadFloat64()
53 if val > float64(math.MaxInt8) || val < float64(math.MinInt8) {
54 iter.ReportError("fuzzy decode int8", "exceed range")
55 return
56 }
57 *((*int8)(ptr)) = int8(val)
58 } else {
59 *((*int8)(ptr)) = iter.ReadInt8()
60 }
61 }})
62 jsoniter.RegisterTypeDecoder("uint8", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
63 if isFloat {
64 val := iter.ReadFloat64()
65 if val > float64(math.MaxUint8) || val < 0 {
66 iter.ReportError("fuzzy decode uint8", "exceed range")
67 return
68 }
69 *((*uint8)(ptr)) = uint8(val)
70 } else {
71 *((*uint8)(ptr)) = iter.ReadUint8()
72 }
73 }})
74 jsoniter.RegisterTypeDecoder("int16", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
75 if isFloat {
76 val := iter.ReadFloat64()
77 if val > float64(math.MaxInt16) || val < float64(math.MinInt16) {
78 iter.ReportError("fuzzy decode int16", "exceed range")
79 return
80 }
81 *((*int16)(ptr)) = int16(val)
82 } else {
83 *((*int16)(ptr)) = iter.ReadInt16()
84 }
85 }})
86 jsoniter.RegisterTypeDecoder("uint16", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
87 if isFloat {
88 val := iter.ReadFloat64()
89 if val > float64(math.MaxUint16) || val < 0 {
90 iter.ReportError("fuzzy decode uint16", "exceed range")
91 return
92 }
93 *((*uint16)(ptr)) = uint16(val)
94 } else {
95 *((*uint16)(ptr)) = iter.ReadUint16()
96 }
97 }})
98 jsoniter.RegisterTypeDecoder("int32", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
99 if isFloat {
100 val := iter.ReadFloat64()
101 if val > float64(math.MaxInt32) || val < float64(math.MinInt32) {
102 iter.ReportError("fuzzy decode int32", "exceed range")
103 return
104 }
105 *((*int32)(ptr)) = int32(val)
106 } else {
107 *((*int32)(ptr)) = iter.ReadInt32()
108 }
109 }})
110 jsoniter.RegisterTypeDecoder("uint32", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
111 if isFloat {
112 val := iter.ReadFloat64()
113 if val > float64(math.MaxUint32) || val < 0 {
114 iter.ReportError("fuzzy decode uint32", "exceed range")
115 return
116 }
117 *((*uint32)(ptr)) = uint32(val)
118 } else {
119 *((*uint32)(ptr)) = iter.ReadUint32()
120 }
121 }})
122 jsoniter.RegisterTypeDecoder("int64", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
123 if isFloat {
124 val := iter.ReadFloat64()
125 if val > float64(math.MaxInt64) || val < float64(math.MinInt64) {
126 iter.ReportError("fuzzy decode int64", "exceed range")
127 return
128 }
129 *((*int64)(ptr)) = int64(val)
130 } else {
131 *((*int64)(ptr)) = iter.ReadInt64()
132 }
133 }})
134 jsoniter.RegisterTypeDecoder("uint64", &fuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
135 if isFloat {
136 val := iter.ReadFloat64()
137 if val > float64(math.MaxUint64) || val < 0 {
138 iter.ReportError("fuzzy decode uint64", "exceed range")
139 return
140 }
141 *((*uint64)(ptr)) = uint64(val)
142 } else {
143 *((*uint64)(ptr)) = iter.ReadUint64()
144 }
145 }})
146 }
147
148 type tolerateEmptyArrayExtension struct {
149 jsoniter.DummyExtension
150 }
151
152 func (extension *tolerateEmptyArrayExtension) DecorateDecoder(typ reflect2.Type, decoder jsoniter.ValDecoder) jsoniter.ValDecoder {
153 if typ.Kind() == reflect.Struct || typ.Kind() == reflect.Map {
154 return &tolerateEmptyArrayDecoder{decoder}
155 }
156 return decoder
157 }
158
159 type tolerateEmptyArrayDecoder struct {
160 valDecoder jsoniter.ValDecoder
161 }
162
163 func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
164 if iter.WhatIsNext() == jsoniter.ArrayValue {
165 iter.Skip()
166 newIter := iter.Pool().BorrowIterator([]byte("{}"))
167 defer iter.Pool().ReturnIterator(newIter)
168 decoder.valDecoder.Decode(ptr, newIter)
169 } else {
170 decoder.valDecoder.Decode(ptr, iter)
171 }
172 }
173
174 type fuzzyStringDecoder struct {
175 }
176
177 func (decoder *fuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
178 valueType := iter.WhatIsNext()
179 switch valueType {
180 case jsoniter.NumberValue:
181 var number json.Number
182 iter.ReadVal(&number)
183 *((*string)(ptr)) = string(number)
184 case jsoniter.StringValue:
185 *((*string)(ptr)) = iter.ReadString()
186 case jsoniter.NilValue:
187 iter.Skip()
188 *((*string)(ptr)) = ""
189 default:
190 iter.ReportError("fuzzyStringDecoder", "not number or string")
191 }
192 }
193
194 type fuzzyIntegerDecoder struct {
195 fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator)
196 }
197
198 func (decoder *fuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
199 valueType := iter.WhatIsNext()
200 var str string
201 switch valueType {
202 case jsoniter.NumberValue:
203 var number json.Number
204 iter.ReadVal(&number)
205 str = string(number)
206 case jsoniter.StringValue:
207 str = iter.ReadString()
208 case jsoniter.BoolValue:
209 if iter.ReadBool() {
210 str = "1"
211 } else {
212 str = "0"
213 }
214 case jsoniter.NilValue:
215 iter.Skip()
216 str = "0"
217 default:
218 iter.ReportError("fuzzyIntegerDecoder", "not number or string")
219 }
220 if len(str) == 0 {
221 str = "0"
222 }
223 newIter := iter.Pool().BorrowIterator([]byte(str))
224 defer iter.Pool().ReturnIterator(newIter)
225 isFloat := strings.IndexByte(str, '.') != -1
226 decoder.fun(isFloat, ptr, newIter)
227 if newIter.Error != nil && newIter.Error != io.EOF {
228 iter.Error = newIter.Error
229 }
230 }
231
232 type fuzzyFloat32Decoder struct {
233 }
234
235 func (decoder *fuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
236 valueType := iter.WhatIsNext()
237 var str string
238 switch valueType {
239 case jsoniter.NumberValue:
240 *((*float32)(ptr)) = iter.ReadFloat32()
241 case jsoniter.StringValue:
242 str = iter.ReadString()
243 newIter := iter.Pool().BorrowIterator([]byte(str))
244 defer iter.Pool().ReturnIterator(newIter)
245 *((*float32)(ptr)) = newIter.ReadFloat32()
246 if newIter.Error != nil && newIter.Error != io.EOF {
247 iter.Error = newIter.Error
248 }
249 case jsoniter.BoolValue:
250
251 if iter.ReadBool() {
252 *((*float32)(ptr)) = 1
253 } else {
254 *((*float32)(ptr)) = 0
255 }
256 case jsoniter.NilValue:
257 iter.Skip()
258 *((*float32)(ptr)) = 0
259 default:
260 iter.ReportError("fuzzyFloat32Decoder", "not number or string")
261 }
262 }
263
264 type fuzzyFloat64Decoder struct {
265 }
266
267 func (decoder *fuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
268 valueType := iter.WhatIsNext()
269 var str string
270 switch valueType {
271 case jsoniter.NumberValue:
272 *((*float64)(ptr)) = iter.ReadFloat64()
273 case jsoniter.StringValue:
274 str = iter.ReadString()
275 newIter := iter.Pool().BorrowIterator([]byte(str))
276 defer iter.Pool().ReturnIterator(newIter)
277 *((*float64)(ptr)) = newIter.ReadFloat64()
278 if newIter.Error != nil && newIter.Error != io.EOF {
279 iter.Error = newIter.Error
280 }
281 case jsoniter.BoolValue:
282
283 if iter.ReadBool() {
284 *((*float64)(ptr)) = 1
285 } else {
286 *((*float64)(ptr)) = 0
287 }
288 case jsoniter.NilValue:
289 iter.Skip()
290 *((*float64)(ptr)) = 0
291 default:
292 iter.ReportError("fuzzyFloat64Decoder", "not number or string")
293 }
294 }
295
View as plain text