github.com/zhangdapeng520/zdpgo_json@v0.1.5/jsoniter/extra/fuzzy_decoder.go (about) 1 package extra 2 3 import ( 4 "encoding/json" 5 "io" 6 "math" 7 "reflect" 8 "strings" 9 "unsafe" 10 11 "github.com/zhangdapeng520/zdpgo_json/jsoniter" 12 "github.com/zhangdapeng520/zdpgo_json/reflect2" 13 ) 14 15 const maxUint = ^uint(0) 16 const maxInt = int(maxUint >> 1) 17 const minInt = -maxInt - 1 18 19 // RegisterFuzzyDecoders decode input from PHP with tolerance. 20 // It will handle string/number auto conversation, and treat empty [] as empty struct. 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 // support bool to float32 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 // support bool to float64 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 }