github.com/alibabacloud-go/tea@v1.3.10/tea/json_parser.go (about)

     1  package tea
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"math"
     7  	"reflect"
     8  	"strconv"
     9  	"strings"
    10  	"unsafe"
    11  
    12  	jsoniter "github.com/json-iterator/go"
    13  	"github.com/modern-go/reflect2"
    14  )
    15  
    16  var jsonParser jsoniter.API
    17  
    18  const maxUint = ^uint(0)
    19  const maxInt = int(maxUint >> 1)
    20  const minInt = -maxInt - 1
    21  
    22  func init() {
    23  	jsonParser = jsoniter.Config{
    24  		EscapeHTML:             true,
    25  		SortMapKeys:            true,
    26  		ValidateJsonRawMessage: true,
    27  		CaseSensitive:          true,
    28  	}.Froze()
    29  
    30  	jsonParser.RegisterExtension(newBetterFuzzyExtension())
    31  }
    32  
    33  func newBetterFuzzyExtension() jsoniter.DecoderExtension {
    34  	return jsoniter.DecoderExtension{
    35  		reflect2.DefaultTypeOfKind(reflect.String):  &nullableFuzzyStringDecoder{},
    36  		reflect2.DefaultTypeOfKind(reflect.Bool):    &fuzzyBoolDecoder{},
    37  		reflect2.DefaultTypeOfKind(reflect.Float32): &nullableFuzzyFloat32Decoder{},
    38  		reflect2.DefaultTypeOfKind(reflect.Float64): &nullableFuzzyFloat64Decoder{},
    39  		reflect2.DefaultTypeOfKind(reflect.Int): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    40  			if isFloat {
    41  				val := iter.ReadFloat64()
    42  				if val > float64(maxInt) || val < float64(minInt) {
    43  					iter.ReportError("fuzzy decode int", "exceed range")
    44  					return
    45  				}
    46  				*((*int)(ptr)) = int(val)
    47  			} else {
    48  				*((*int)(ptr)) = iter.ReadInt()
    49  			}
    50  		}},
    51  		reflect2.DefaultTypeOfKind(reflect.Uint): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    52  			if isFloat {
    53  				val := iter.ReadFloat64()
    54  				if val > float64(maxUint) || val < 0 {
    55  					iter.ReportError("fuzzy decode uint", "exceed range")
    56  					return
    57  				}
    58  				*((*uint)(ptr)) = uint(val)
    59  			} else {
    60  				*((*uint)(ptr)) = iter.ReadUint()
    61  			}
    62  		}},
    63  		reflect2.DefaultTypeOfKind(reflect.Int8): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    64  			if isFloat {
    65  				val := iter.ReadFloat64()
    66  				if val > float64(math.MaxInt8) || val < float64(math.MinInt8) {
    67  					iter.ReportError("fuzzy decode int8", "exceed range")
    68  					return
    69  				}
    70  				*((*int8)(ptr)) = int8(val)
    71  			} else {
    72  				*((*int8)(ptr)) = iter.ReadInt8()
    73  			}
    74  		}},
    75  		reflect2.DefaultTypeOfKind(reflect.Uint8): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    76  			if isFloat {
    77  				val := iter.ReadFloat64()
    78  				if val > float64(math.MaxUint8) || val < 0 {
    79  					iter.ReportError("fuzzy decode uint8", "exceed range")
    80  					return
    81  				}
    82  				*((*uint8)(ptr)) = uint8(val)
    83  			} else {
    84  				*((*uint8)(ptr)) = iter.ReadUint8()
    85  			}
    86  		}},
    87  		reflect2.DefaultTypeOfKind(reflect.Int16): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    88  			if isFloat {
    89  				val := iter.ReadFloat64()
    90  				if val > float64(math.MaxInt16) || val < float64(math.MinInt16) {
    91  					iter.ReportError("fuzzy decode int16", "exceed range")
    92  					return
    93  				}
    94  				*((*int16)(ptr)) = int16(val)
    95  			} else {
    96  				*((*int16)(ptr)) = iter.ReadInt16()
    97  			}
    98  		}},
    99  		reflect2.DefaultTypeOfKind(reflect.Uint16): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   100  			if isFloat {
   101  				val := iter.ReadFloat64()
   102  				if val > float64(math.MaxUint16) || val < 0 {
   103  					iter.ReportError("fuzzy decode uint16", "exceed range")
   104  					return
   105  				}
   106  				*((*uint16)(ptr)) = uint16(val)
   107  			} else {
   108  				*((*uint16)(ptr)) = iter.ReadUint16()
   109  			}
   110  		}},
   111  		reflect2.DefaultTypeOfKind(reflect.Int32): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   112  			if isFloat {
   113  				val := iter.ReadFloat64()
   114  				if val > float64(math.MaxInt32) || val < float64(math.MinInt32) {
   115  					iter.ReportError("fuzzy decode int32", "exceed range")
   116  					return
   117  				}
   118  				*((*int32)(ptr)) = int32(val)
   119  			} else {
   120  				*((*int32)(ptr)) = iter.ReadInt32()
   121  			}
   122  		}},
   123  		reflect2.DefaultTypeOfKind(reflect.Uint32): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   124  			if isFloat {
   125  				val := iter.ReadFloat64()
   126  				if val > float64(math.MaxUint32) || val < 0 {
   127  					iter.ReportError("fuzzy decode uint32", "exceed range")
   128  					return
   129  				}
   130  				*((*uint32)(ptr)) = uint32(val)
   131  			} else {
   132  				*((*uint32)(ptr)) = iter.ReadUint32()
   133  			}
   134  		}},
   135  		reflect2.DefaultTypeOfKind(reflect.Int64): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   136  			if isFloat {
   137  				val := iter.ReadFloat64()
   138  				if val > float64(math.MaxInt64) || val < float64(math.MinInt64) {
   139  					iter.ReportError("fuzzy decode int64", "exceed range")
   140  					return
   141  				}
   142  				*((*int64)(ptr)) = int64(val)
   143  			} else {
   144  				*((*int64)(ptr)) = iter.ReadInt64()
   145  			}
   146  		}},
   147  		reflect2.DefaultTypeOfKind(reflect.Uint64): &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   148  			if isFloat {
   149  				val := iter.ReadFloat64()
   150  				if val > float64(math.MaxUint64) || val < 0 {
   151  					iter.ReportError("fuzzy decode uint64", "exceed range")
   152  					return
   153  				}
   154  				*((*uint64)(ptr)) = uint64(val)
   155  			} else {
   156  				*((*uint64)(ptr)) = iter.ReadUint64()
   157  			}
   158  		}},
   159  	}
   160  }
   161  
   162  type nullableFuzzyStringDecoder struct {
   163  }
   164  
   165  func (decoder *nullableFuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   166  	valueType := iter.WhatIsNext()
   167  	switch valueType {
   168  	case jsoniter.NumberValue:
   169  		var number json.Number
   170  		iter.ReadVal(&number)
   171  		*((*string)(ptr)) = string(number)
   172  	case jsoniter.StringValue:
   173  		*((*string)(ptr)) = iter.ReadString()
   174  	case jsoniter.BoolValue:
   175  		*((*string)(ptr)) = strconv.FormatBool(iter.ReadBool())
   176  	case jsoniter.NilValue:
   177  		iter.ReadNil()
   178  		*((*string)(ptr)) = ""
   179  	default:
   180  		iter.ReportError("fuzzyStringDecoder", "not number or string or bool")
   181  	}
   182  }
   183  
   184  type fuzzyBoolDecoder struct {
   185  }
   186  
   187  func (decoder *fuzzyBoolDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   188  	valueType := iter.WhatIsNext()
   189  	switch valueType {
   190  	case jsoniter.BoolValue:
   191  		*((*bool)(ptr)) = iter.ReadBool()
   192  	case jsoniter.NumberValue:
   193  		var number json.Number
   194  		iter.ReadVal(&number)
   195  		num, err := number.Int64()
   196  		if err != nil {
   197  			iter.ReportError("fuzzyBoolDecoder", "get value from json.number failed")
   198  		}
   199  		if num == 0 {
   200  			*((*bool)(ptr)) = false
   201  		} else {
   202  			*((*bool)(ptr)) = true
   203  		}
   204  	case jsoniter.StringValue:
   205  		strValue := strings.ToLower(iter.ReadString())
   206  		if strValue == "true" {
   207  			*((*bool)(ptr)) = true
   208  		} else if strValue == "false" || strValue == "" {
   209  			*((*bool)(ptr)) = false
   210  		} else {
   211  			iter.ReportError("fuzzyBoolDecoder", "unsupported bool value: "+strValue)
   212  		}
   213  	case jsoniter.NilValue:
   214  		iter.ReadNil()
   215  		*((*bool)(ptr)) = false
   216  	default:
   217  		iter.ReportError("fuzzyBoolDecoder", "not number or string or nil")
   218  	}
   219  }
   220  
   221  type nullableFuzzyIntegerDecoder struct {
   222  	fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator)
   223  }
   224  
   225  func (decoder *nullableFuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   226  	valueType := iter.WhatIsNext()
   227  	var str string
   228  	switch valueType {
   229  	case jsoniter.NumberValue:
   230  		var number json.Number
   231  		iter.ReadVal(&number)
   232  		str = string(number)
   233  	case jsoniter.StringValue:
   234  		str = iter.ReadString()
   235  		// support empty string
   236  		if str == "" {
   237  			str = "0"
   238  		}
   239  	case jsoniter.BoolValue:
   240  		if iter.ReadBool() {
   241  			str = "1"
   242  		} else {
   243  			str = "0"
   244  		}
   245  	case jsoniter.NilValue:
   246  		iter.ReadNil()
   247  		str = "0"
   248  	default:
   249  		iter.ReportError("fuzzyIntegerDecoder", "not number or string")
   250  	}
   251  	newIter := iter.Pool().BorrowIterator([]byte(str))
   252  	defer iter.Pool().ReturnIterator(newIter)
   253  	isFloat := strings.IndexByte(str, '.') != -1
   254  	decoder.fun(isFloat, ptr, newIter)
   255  	if newIter.Error != nil && newIter.Error != io.EOF {
   256  		iter.Error = newIter.Error
   257  	}
   258  }
   259  
   260  type nullableFuzzyFloat32Decoder struct {
   261  }
   262  
   263  func (decoder *nullableFuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   264  	valueType := iter.WhatIsNext()
   265  	var str string
   266  	switch valueType {
   267  	case jsoniter.NumberValue:
   268  		*((*float32)(ptr)) = iter.ReadFloat32()
   269  	case jsoniter.StringValue:
   270  		str = iter.ReadString()
   271  		// support empty string
   272  		if str == "" {
   273  			*((*float32)(ptr)) = 0
   274  			return
   275  		}
   276  		newIter := iter.Pool().BorrowIterator([]byte(str))
   277  		defer iter.Pool().ReturnIterator(newIter)
   278  		*((*float32)(ptr)) = newIter.ReadFloat32()
   279  		if newIter.Error != nil && newIter.Error != io.EOF {
   280  			iter.Error = newIter.Error
   281  		}
   282  	case jsoniter.BoolValue:
   283  		// support bool to float32
   284  		if iter.ReadBool() {
   285  			*((*float32)(ptr)) = 1
   286  		} else {
   287  			*((*float32)(ptr)) = 0
   288  		}
   289  	case jsoniter.NilValue:
   290  		iter.ReadNil()
   291  		*((*float32)(ptr)) = 0
   292  	default:
   293  		iter.ReportError("nullableFuzzyFloat32Decoder", "not number or string")
   294  	}
   295  }
   296  
   297  type nullableFuzzyFloat64Decoder struct {
   298  }
   299  
   300  func (decoder *nullableFuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   301  	valueType := iter.WhatIsNext()
   302  	var str string
   303  	switch valueType {
   304  	case jsoniter.NumberValue:
   305  		*((*float64)(ptr)) = iter.ReadFloat64()
   306  	case jsoniter.StringValue:
   307  		str = iter.ReadString()
   308  		// support empty string
   309  		if str == "" {
   310  			*((*float64)(ptr)) = 0
   311  			return
   312  		}
   313  		newIter := iter.Pool().BorrowIterator([]byte(str))
   314  		defer iter.Pool().ReturnIterator(newIter)
   315  		*((*float64)(ptr)) = newIter.ReadFloat64()
   316  		if newIter.Error != nil && newIter.Error != io.EOF {
   317  			iter.Error = newIter.Error
   318  		}
   319  	case jsoniter.BoolValue:
   320  		// support bool to float64
   321  		if iter.ReadBool() {
   322  			*((*float64)(ptr)) = 1
   323  		} else {
   324  			*((*float64)(ptr)) = 0
   325  		}
   326  	case jsoniter.NilValue:
   327  		// support empty string
   328  		iter.ReadNil()
   329  		*((*float64)(ptr)) = 0
   330  	default:
   331  		iter.ReportError("nullableFuzzyFloat64Decoder", "not number or string")
   332  	}
   333  }