package jsoniter import ( "encoding/json" "github.com/modern-go/reflect2" "strconv" "unsafe" ) type Number string // String returns the literal text of the number. func (n Number) String() string { return string(n) } // Float64 returns the number as a float64. func (n Number) Float64() (float64, error) { return strconv.ParseFloat(string(n), 64) } // Int64 returns the number as an int64. func (n Number) Int64() (int64, error) { return strconv.ParseInt(string(n), 10, 64) } func CastJsonNumber(val interface{}) (string, bool) { switch typedVal := val.(type) { case json.Number: return string(typedVal), true case Number: return string(typedVal), true } return "", false } var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem() var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem() func createDecoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValDecoder { if typ.AssignableTo(jsonNumberType) { return &jsonNumberCodec{} } if typ.AssignableTo(jsoniterNumberType) { return &jsoniterNumberCodec{} } return nil } func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder { if typ.AssignableTo(jsonNumberType) { return &jsonNumberCodec{} } if typ.AssignableTo(jsoniterNumberType) { return &jsoniterNumberCodec{} } return nil } type jsonNumberCodec struct { } func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { switch iter.WhatIsNext() { case StringValue: *((*json.Number)(ptr)) = json.Number(iter.ReadString()) case NilValue: iter.skipFourBytes('n', 'u', 'l', 'l') *((*json.Number)(ptr)) = "" default: *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString())) } } func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { number := *((*json.Number)(ptr)) if len(number) == 0 { stream.writeByte('0') } else { stream.WriteRaw(string(number)) } } func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*json.Number)(ptr))) == 0 } type jsoniterNumberCodec struct { } func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { switch iter.WhatIsNext() { case StringValue: *((*Number)(ptr)) = Number(iter.ReadString()) case NilValue: iter.skipFourBytes('n', 'u', 'l', 'l') *((*Number)(ptr)) = "" default: *((*Number)(ptr)) = Number([]byte(iter.readNumberAsString())) } } func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { number := *((*Number)(ptr)) if len(number) == 0 { stream.writeByte('0') } else { stream.WriteRaw(string(number)) } } func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*Number)(ptr))) == 0 }