golang源码分析:json-iterator/go(2)

2023-09-06 19:18:43 浏览数 (2)

接着分析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)

0 人点赞