接着分析json-iterator的源码,首先从序列化函数入手
代码语言:javascript复制b, err := jsoniter.Marshal(group)
它的定义位于github.com/json-iterator/go@v1.1.12/adapter.go
代码语言:javascript复制func Marshal(v interface{}) ([]byte, error) {
return ConfigDefault.Marshal(v)
}
其中ConfigDefault是一个全局变量:github.com/json-iterator/go@v1.1.12/config.go
代码语言:javascript复制var ConfigDefault = Config{
EscapeHTML: true,
}.Froze()
其中定义了各种pool和cache提供缓存能力来提升性能:
代码语言:javascript复制func (cfg Config) Froze() API {
api := &frozenConfig{
api.streamPool = &sync.Pool{
api.iteratorPool = &sync.Pool{
cfg.decoderCache = concurrent.NewMap()
cfg.encoderCache = concurrent.NewMap()
encoderExtension := EncoderExtension{}
decoderExtension := DecoderExtension{}
接口我们看下它的序列化函数,它调用了WriteVal
代码语言:javascript复制func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
stream := cfg.BorrowStream(nil)
stream.WriteVal(v)
result := stream.Buffer()
github.com/json-iterator/go@v1.1.12/reflect.go,它通过反射获取类型,然后通过类型找到对应的编码函数,最后通过Encode方法进行编码,查找过程中优先从cache里获取:
代码语言:javascript复制func (stream *Stream) WriteVal(val interface{}) {
cacheKey := reflect2.RTypeOf(val)
encoder := stream.cfg.getEncoderFromCache(cacheKey)
typ := reflect2.TypeOf(val)
encoder = stream.cfg.EncoderOf(typ)
encoder.Encode(reflect2.PtrOf(val), stream)
代码语言:javascript复制func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder {
cacheKey := typ.RType()
encoder = encoderOfType(ctx, typ)
if typ.LikePtr() {
encoder = &onePtrEncoder{encoder}
}
代码语言:javascript复制func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := getTypeEncoderFromExtension(ctx, typ)
encoder = createEncoderOfType(ctx, typ)
如果没有找到,就创建一个
代码语言:javascript复制func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
placeholder := &placeholderEncoder{}
ctx.encoders[typ] = placeholder
encoder = _createEncoderOfType(ctx, typ)
placeholder.encoder = encoder
可以看到,它优先根据类型,获取RawMessahge,JsonNumber,Marshaler,Any,Native几种类型的编码函数,获取不到,根据Kind,获取基本类型的编码函数:
代码语言:javascript复制func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := createEncoderOfJsonRawMessage(ctx, typ)
encoder = createEncoderOfJsonNumber(ctx, typ)
encoder = createEncoderOfMarshaler(ctx, typ)
encoder = createEncoderOfAny(ctx, typ)
encoder = createEncoderOfNative(ctx, typ)
kind := typ.Kind()
switch kind {
case reflect.Interface:
return &dynamicEncoder{typ}
case reflect.Struct:
return encoderOfStruct(ctx, typ)
case reflect.Array:
return encoderOfArray(ctx, typ)
case reflect.Slice:
return encoderOfSlice(ctx, typ)
case reflect.Map:
return encoderOfMap(ctx, typ)
case reflect.Ptr:
return encoderOfOptional(ctx, typ)
default:
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
}
如果是Interface类型,它使用dynamicEncoder,定义位于:github.com/json-iterator/go@v1.1.12/reflect_dynamic.go
代码语言:javascript复制type dynamicEncoder struct {
valType reflect2.Type
}
代码语言:javascript复制func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
obj := encoder.valType.UnsafeIndirect(ptr)
stream.WriteVal(obj)
}
struct类型的encoder定义位于:
github.com/json-iterator/go@v1.1.12/reflect_struct_encoder.go
代码语言:javascript复制func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder {
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames {
for _, old := range orderedBindings {
它先获取结构体类型的描述信息,然后通过遍历描述信息的字段,以及绑定的名称,最后进行每个字段的递归处理。
json数字的处理定义位于:github.com/json-iterator/go@v1.1.12/reflect_json_number.go,里面有两个分支,分布对应json的Number和jsoniter的Number类型。
代码语言:javascript复制func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}
}
if typ.AssignableTo(jsoniterNumberType) {
return &jsoniterNumberCodec{}
}
return nil
}
他俩都是通过反射获取的对象的类型信息:
代码语言:javascript复制var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem()
var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem()
对应的,解码函数定义如下:
代码语言:javascript复制type jsonNumberCodec struct {
}
代码语言:javascript复制func (codec *jsonNumberCodec) 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()))
}
字符串原位赋值,不解析,所以没有内存分配和释放,速度很快,不错的想法。指针指向json中的位置。编码函数其实就是简单地将函数转换成字符串。
代码语言:javascript复制func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(number))
代码语言:javascript复制type Number string
// String returns the literal text of the number.
func (n Number) String() string { return string(n) }
代码语言:javascript复制// Float64 returns the number as a float64.
func (n Number) Float64() (float64, error) {
return strconv.ParseFloat(string(n), 64)
}
代码语言:javascript复制// Int64 returns the number as an int64.
func (n Number) Int64() (int64, error) {
return strconv.ParseInt(string(n), 10, 64)
}
类似的浮点数处理也一样,先按照字符串读取,这样可以避免内存分配,然后按需解析:github.com/json-iterator/go@v1.1.12/iter_float.go
代码语言:javascript复制func (iter *Iterator) readNumberAsString() (ret string) {
for {
for i := iter.head; i < iter.tail; i {
c := iter.buf[i]
switch c {
case ' ', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
str = append(str, c)
类型的解析,会通过map来缓存类型和对应解析函数的关联关系:github.com/json-iterator/go@v1.1.12/reflect_extension.go
代码语言:javascript复制type EncoderExtension map[reflect2.Type]ValEncoder
type DecoderExtension map[reflect2.Type]ValDecoder
对于结构体来说,describeStruct通过反射获取类型,然后解析出其描述信息,对于它的每个field可以进行递归处理:
代码语言:javascript复制func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
structType := typ.(*reflect2.UnsafeStructType)
for i := 0; i < structType.NumField(); i {
if field.Type().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, field.Type())
for _, binding := range structDescriptor.Fields {
binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty}
binding.Decoder = &structFieldDecoder{field, binding.Decoder}
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
最后创建 StructDescriptor,的实例:
代码语言:javascript复制func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
for _, extension := range extensions {
extension.UpdateStructDescriptor(structDescriptor)
其中用到的反射并不是golang原生的反射,而是新封装的:
github.com/modern-go/reflect2@v1.0.2/reflect2.go,它实现了如下接口:
代码语言:javascript复制type Type interface {
Kind() reflect.Kind
// New return pointer to data of this type
New() interface{}
// UnsafeNew return the allocated space pointed by unsafe.Pointer
UnsafeNew() unsafe.Pointer
// PackEFace cast a unsafe pointer to object represented pointer
PackEFace(ptr unsafe.Pointer) interface{}
// Indirect dereference object represented pointer to this type
Indirect(obj interface{}) interface{}
// UnsafeIndirect dereference pointer to this type
UnsafeIndirect(ptr unsafe.Pointer) interface{}
// Type1 returns reflect.Type
Type1() reflect.Type
Implements(thatType Type) bool
String() string
RType() uintptr
// interface{} of this type has pointer like behavior
LikePtr() bool
IsNullable() bool
IsNil(obj interface{}) bool
UnsafeIsNil(ptr unsafe.Pointer) bool
Set(obj interface{}, val interface{})
UnsafeSet(ptr unsafe.Pointer, val unsafe.Pointer)
AssignableTo(anotherType Type) bool
}
介绍完序列化函数,我们来分析下反序列化函数:
代码语言:javascript复制json.Unmarshal(b, &data)
它的入口位于:github.com/json-iterator/go@v1.1.12/config.go,调用了迭代器的ReadVal函数:
代码语言:javascript复制func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
iter.ReadVal(v)
c := iter.nextToken()
具体定义位于:github.com/json-iterator/go@v1.1.12/reflect.go,先从cache获取decoder,获取失败,通过反射获取类型信息,然后通过类型获取decoder,最后调用decoder的Decode方法来进行json解析:
代码语言:javascript复制func (iter *Iterator) ReadVal(obj interface{}) {
cacheKey := reflect2.RTypeOf(obj)
decoder := iter.cfg.getDecoderFromCache(cacheKey)
typ := reflect2.TypeOf(obj)
decoder = iter.cfg.DecoderOf(typ)
ptr := reflect2.PtrOf(obj)
decoder.Decode(ptr, iter)
代码语言:javascript复制func (cfg *frozenConfig) DecoderOf(typ reflect2.Type) ValDecoder {
ctx := &ctx{
frozenConfig: cfg,
prefix: "",
decoders: map[reflect2.Type]ValDecoder{},
encoders: map[reflect2.Type]ValEncoder{},
}
ptrType := typ.(*reflect2.UnsafePtrType)
decoder = decoderOfType(ctx, ptrType.Elem())
如果缓存拿不到,就创建这种类型的decoder:
代码语言:javascript复制func decoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := getTypeDecoderFromExtension(ctx, typ)
decoder = createDecoderOfType(ctx, typ)
decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder)
和获取编码函数的方式类似:
代码语言:javascript复制func createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
placeholder := &placeholderDecoder{}
ctx.decoders[typ] = placeholder
decoder = _createDecoderOfType(ctx, typ)
placeholder.decoder = decoder
自定义类型的解码器如果没有找到,就根据Kind,获取基本类型的解码器:
代码语言:javascript复制func _createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := createDecoderOfJsonRawMessage(ctx, typ)
decoder = createDecoderOfJsonNumber(ctx, typ)
decoder = createDecoderOfMarshaler(ctx, typ)
decoder = createDecoderOfAny(ctx, typ)
decoder = createDecoderOfNative(ctx, typ)
switch typ.Kind() {
case reflect.Interface:
ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType)
if isIFace {
return &ifaceDecoder{valType: ifaceType}
}
return &efaceDecoder{}
case reflect.Struct:
return decoderOfStruct(ctx, typ)
case reflect.Array:
return decoderOfArray(ctx, typ)
case reflect.Slice:
return decoderOfSlice(ctx, typ)
case reflect.Map:
return decoderOfMap(ctx, typ)
case reflect.Ptr:
return decoderOfOptional(ctx, typ)
default:
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
}
}
获取类型的过程,的TypeOf是通过指针直接获取的:github.com/modern-go/reflect2@v1.0.2/reflect2.go
代码语言:javascript复制func RTypeOf(obj interface{}) uintptr {
return uintptr(unpackEFace(obj).rtype)
}
代码语言:javascript复制func TypeOf(obj interface{}) Type {
return ConfigUnsafe.TypeOf(obj)
}
代码语言:javascript复制func (cfg *frozenConfig) TypeOf(obj interface{}) Type {
cacheKey := uintptr(unpackEFace(obj).rtype)
typeObj, found := cfg.cache.Load(cacheKey)
if found {
return typeObj.(Type)
}
return cfg.Type2(reflect.TypeOf(obj))
}
代码语言:javascript复制func (cfg *frozenConfig) Type2(type1 reflect.Type) Type {
type2 := cfg.wrapType(type1
代码语言:javascript复制func (cfg *frozenConfig) wrapType(type1 reflect.Type) Type {
safeType := safeType{Type: type1, cfg: cfg}
switch type1.Kind() {
case reflect.Struct:
if cfg.useSafeImplementation {
return &safeStructType{safeType}
}
return newUnsafeStructType(cfg, type1)
case reflect.Array:
if cfg.useSafeImplementation {
return &safeSliceType{safeType}
}
return newUnsafeArrayType(cfg, type1)
case reflect.Slice:
if cfg.useSafeImplementation {
return &safeSliceType{safeType}
}
return newUnsafeSliceType(cfg, type1)
case reflect.Map:
if cfg.useSafeImplementation {
return &safeMapType{safeType}
}
return newUnsafeMapType(cfg, type1)
case reflect.Ptr, reflect.Chan, reflect.Func:
if cfg.useSafeImplementation {
return &safeMapType{safeType}
}
return newUnsafePtrType(cfg, type1)
case reflect.Interface:
if cfg.useSafeImplementation {
return &safeMapType{safeType}
}
if type1.NumMethod() == 0 {
return newUnsafeEFaceType(cfg, type1)
}
return newUnsafeIFaceType(cfg, type1)
default:
if cfg.useSafeImplementation {
return &safeType
}
return newUnsafeType(cfg, type1)
}
}
github.com/modern-go/reflect2@v1.0.2/unsafe_eface.go
代码语言:javascript复制func unpackEFace(obj interface{}) *eface {
return (*eface)(unsafe.Pointer(&obj))
}
获取类型的解码函数后,我们就可以通过iter迭代器来沿着json字符串进行解析了:github.com/json-iterator/go@v1.1.12/iter.go,比如nextToken用于过滤空格
代码语言:javascript复制func (iter *Iterator) nextToken() byte {
// a variation of skip whitespaces, returning the next non-whitespace token
for {
for i := iter.head; i < iter.tail; i {
c := iter.buf[i]
switch c {
case ' ', 'n', 't', 'r':
continue
下面详细介绍下结构体的解码器是如何定义的:github.com/json-iterator/go@v1.1.12/reflect_struct_decoder.go,先获取结构体的描述信息,然后根据描述信息里的Fieds,递归获取解码器,然后通过map缓存,方便后面获取:
代码语言:javascript复制func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder {
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames {
ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding)
fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder)
}
return createStructDecoder(ctx, typ, fields)
注意这里有个优化,在字段少于10个的结构体,直接在内存定义字段key的hash值和对应的解码函数,匹配的时候可以通过hash值匹配,然后找到解码函数,不用走map的申请和匹配,提升速度。超过10个则退化到map查找:
代码语言:javascript复制func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder {
switch len(fields) {
case 0:
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}
}
case 10:
代码语言:javascript复制type generalStructDecoder struct {
typ reflect2.Type
fields map[string]*structFieldDecoder
disallowUnknownFields bool
}
代码语言:javascript复制type structFieldDecoder struct {
field reflect2.StructField
fieldDecoder ValDecoder
}
decoder的定义是个递归的过程:
代码语言:javascript复制func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := decoder.field.UnsafeGet(ptr)
decoder.fieldDecoder.Decode(fieldPtr, iter)
值的解码定义位于:github.com/json-iterator/go@v1.1.12/reflect.go
代码语言:javascript复制type ValDecoder interface {
Decode(ptr unsafe.Pointer, iter *Iterator)
}
代码语言:javascript复制// ValDecoder is an internal type registered to cache as needed.
// Don't confuse jsoniter.ValDecoder with json.Decoder.
// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link).
//
// Reflection on type to create decoders, which is then cached
// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions
// 1. create instance of new value, for example *int will need a int to be allocated
// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New
// 3. assignment to map, both key and value will be reflect.Value
// For a simple struct binding, it will be reflect.Value free and allocation free
native类型的解码器定义位于:github.com/json-iterator/go@v1.1.12/reflect_native.go,可以看到,对于每一种基础类型,都定义了对应的解码器:
代码语言:javascript复制func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 {
sliceDecoder := decoderOfSlice(ctx, typ)
return &base64Codec{sliceDecoder: sliceDecoder}
}
typeName := typ.String()
switch typ.Kind() {
case reflect.String:
if typeName != "string" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &int32Codec{}
}
return &int64Codec{}
case reflect.Int8:
if typeName != "int8" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint8:
if typeName != "uint8" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem())
}
if ptrSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint64:
if typeName != "uint64" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem())
}
return &boolCodec{}
}
return nil
}
代码语言:javascript复制type boolCodec struct {
}
代码语言:javascript复制func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*bool)(ptr)) = iter.ReadBool()
}
}
bool解码器,本质上就是把json字符串中的true,false解析成bool值:
代码语言:javascript复制func (iter *Iterator) ReadBool() (ret bool) {
c := iter.nextToken()
if c == 't' {
iter.skipThreeBytes('r', 'u', 'e')
return true
}
if c == 'f' {
iter.skipFourBytes('a', 'l', 's', 'e')
return false
}
iter.ReportError("ReadBool", "expect t or f, but found " string([]byte{c}))
return
}
类似浮点数:
代码语言:javascript复制 type float32Codec struct {
}
代码语言:javascript复制func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*float32)(ptr)) = iter.ReadFloat32()
}
}
代码语言:javascript复制func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat32(*((*float32)(ptr)))
}
代码语言:javascript复制//ReadFloat32 read float32
func (iter *Iterator) ReadFloat32() (ret float32) {
c := iter.nextToken()
if c == '-' {
return -iter.readPositiveFloat32()
}
iter.unreadByte()
return iter.readPositiveFloat32()
}
浮点数的解析过程中,直接通过字符的值,最后计算出浮点数的值:
代码语言:javascript复制func (iter *Iterator) readPositiveFloat32() (ret float32) {
i := iter.head
// first char
if i == iter.tail {
return iter.readFloat32SlowPath()
}
c := iter.buf[i]
i
ind := floatDigits[c]
switch ind {
case invalidCharForNumber:
return iter.readFloat32SlowPath()
case endOfNumber:
iter.ReportError("readFloat32", "empty number")
return
case dotInNumber:
iter.ReportError("readFloat32", "leading dot is invalid")
return
case 0:
if i == iter.tail {
return iter.readFloat32SlowPath()
}
c = iter.buf[i]
switch c {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
iter.ReportError("readFloat32", "leading zero is invalid")
return
}
}
value := uint64(ind)
// chars before dot
non_decimal_loop:
for ; i < iter.tail; i {
c = iter.buf[i]
ind := floatDigits[c]
switch ind {
case invalidCharForNumber:
return iter.readFloat32SlowPath()
case endOfNumber:
iter.head = i
return float32(value)
case dotInNumber:
break non_decimal_loop
}
if value > uint64SafeToMultiple10 {
return iter.readFloat32SlowPath()
}
value = (value << 3) (value << 1) uint64(ind) // value = value * 10 ind;
}
// chars after dot
if c == '.' {
i
decimalPlaces := 0
if i == iter.tail {
return iter.readFloat32SlowPath()
}
for ; i < iter.tail; i {
c = iter.buf[i]
ind := floatDigits[c]
switch ind {
case endOfNumber:
if decimalPlaces > 0 && decimalPlaces < len(pow10) {
iter.head = i
return float32(float64(value) / float64(pow10[decimalPlaces]))
}
// too many decimal places
return iter.readFloat32SlowPath()
case invalidCharForNumber, dotInNumber:
return iter.readFloat32SlowPath()
}
decimalPlaces
if value > uint64SafeToMultiple10 {
return iter.readFloat32SlowPath()
}
value = (value << 3) (value << 1) uint64(ind)
}
}
return iter.readFloat32SlowPath()
}
github.com/json-iterator/go@v1.1.12/reflect_extension.go结构体的描述信息是通过反射,获取结构体的字段信息,最后组建的:
代码语言:javascript复制func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
for i := 0; i < structType.NumField(); i {
field := structType.Field(i)
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
fieldNames := calcFieldNames(field.Name(), tagParts[0], tag)
decoder = decoderOfType(ctx.append(field.Name()), field.Type())
binding := &Binding{
Field: field,
FromNames: fieldNames,
ToNames: fieldNames,
Decoder: decoder,
Encoder: encoder,
}
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
json迭代器的定义位于github.com/json-iterator/go@v1.1.12/iter.go
代码语言:javascript复制type Iterator struct {
cfg *frozenConfig
reader io.Reader
buf []byte
head int
tail int
depth int
captureStartedAt int
captured []byte
Error error
Attachment interface{} // open for customized decoder
}
read函数不断向后读取字符,并根据获得的key,找到val对应的类型和对应的解析函数,最后调用解析函数,完成解析和绑定:
代码语言:javascript复制func (iter *Iterator) Read() interface{} {
valueType := iter.WhatIsNext()
switch valueType {
case StringValue:
return iter.ReadString()
case NumberValue:
比如结构体的解析位于:
github.com/json-iterator/go@v1.1.12/reflect_struct_decoder.go
代码语言:javascript复制func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
for c = ','; c == ','; c = iter.nextToken() {
decoder.decodeOneField(ptr, iter)
}
代码语言:javascript复制type structFieldDecoder struct {
field reflect2.StructField
fieldDecoder ValDecoder
}
代码语言:javascript复制func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := decoder.field.UnsafeGet(ptr)
decoder.fieldDecoder.Decode(fieldPtr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name(), iter.Error.Error())
}
}
可以看到每个字段的解析过程
代码语言:javascript复制func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) {
field = iter.ReadString()
fieldDecoder = decoder.fields[field]
if fieldDecoder == nil && !iter.cfg.caseSensitive {
fieldDecoder = decoder.fields[strings.ToLower(field)]
}
c := iter.nextToken()
if c != ':' {
c := iter.nextToken()
fieldDecoder.Decode(ptr, iter)
先解析出结构体每个field的标识,存入标识到解析方法的影射的map里,供后面解析使用。解析的时候,解析出json的对象后,根据key string到field里面去查,时间复杂度O(1),得到value的解析函数,如此递归。
代码语言:javascript复制type generalStructDecoder struct {
typ reflect2.Type
fields map[string]*structFieldDecoder
disallowUnknownFields bool
}
代码语言:javascript复制func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
for c = ','; c == ','; c = iter.nextToken() {
decoder.decodeOneField(ptr, iter)
}
iter.decrementDepth()
代码语言:javascript复制type tenFieldsStructDecoder struct {
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
fieldHash8 int64
fieldDecoder8 *structFieldDecoder
fieldHash9 int64
fieldDecoder9 *structFieldDecoder
fieldHash10 int64
fieldDecoder10 *structFieldDecoder
}
小于10个的时候,自己做了hash,避免了,map的寻址,直接进行结构体的字段和hash值匹配,从json里直接计算key的hash,通过内存运算加速。
代码语言:javascript复制func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
for {
switch iter.readFieldHash() {
case decoder.fieldHash1:
decoder.fieldDecoder1.Decode(ptr, iter)
代码语言:javascript复制func (iter *Iterator) readFieldHash() int64 {
for {
for i := iter.head; i < iter.tail; i {
// require ascii string and no escape
b := iter.buf[i]
if b == '\' {
iter.head = i
for _, b := range iter.readStringSlowPath() {
if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
b = 'a' - 'A'
}
hash ^= int64(b)
hash *= 0x1000193
}
return &generalStructDecoder{typ, fields, false}
超过10个字段,使用上面的通用decoder来解码:
代码语言:javascript复制func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
for c = ','; c == ','; c = iter.nextToken() {
decoder.decodeOneField(ptr, iter)
}
超过10个字段的场景,依次遍历当前json对象内部的所有字段,尝试进行,和go 结构体的每个field进行匹配,field照样是到map里面去取:
代码语言:javascript复制func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) {
fieldDecoder.Decode(ptr, iter)
代码语言:javascript复制func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := decoder.field.UnsafeGet(ptr)
decoder.fieldDecoder.Decode(fieldPtr, iter)
代码语言:javascript复制func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder {
for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder)
}
if !ctx.caseSensitive() {
for k, binding := range bindings {
if _, found := fields[strings.ToLower(k)]; !found {
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
return createStructDecoder(ctx, typ, fields)
github.com/json-iterator/go@v1.1.12/reflect_extension.go可以看到结构体描述信息是如何组装的:
代码语言:javascript复制func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
bindings := []*Binding{}
for i := 0; i < structType.NumField(); i {
binding := &Binding{
Field: field,
FromNames: fieldNames,
ToNames: fieldNames,
Decoder: decoder,
Encoder: encoder,
}
bindings = append(bindings, binding)
组装完成后会对描述信息排序,方便后面加速查找:
代码语言:javascript复制func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
sort.Sort(allBindings)