Golang

关于jsoniter源码-Marshal

2018-12-10  本文已影响28人  神奇的考拉

在使用jsoniter来做json相关的Marshal和UnMarshal其实是比较简单的,仅需要一行代码:

type ColorGroup struct {
    ID      int
    Name    string
    Colors  []string
}

group := ColorGroup{
        ID:     1,
        Name:   "Reds",
        Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
}
// 直接使用adapter.go里面的Marshal方法即可完成, so easy
b, err := jsoniter.Marshal(group)

接下来我们不是来证明jsoniter的简单和任性,而是要梳理下Marshal操作的流程:
当我们在执行jsoniter.Matshal(xxx),其中xxx为要转化的实体:
1.通过使用config.go中定义ConfigDefault.Marshal(XXX)来进行的

func (cfg Config) Froze() API {
    api := &frozenConfig{
        sortMapKeys:                   cfg.SortMapKeys,
        indentionStep:                 cfg.IndentionStep,
        objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
        onlyTaggedField:               cfg.OnlyTaggedField,
        disallowUnknownFields:         cfg.DisallowUnknownFields,
        caseSensitive:                 cfg.CaseSensitive,
    }
    api.streamPool = &sync.Pool{                    // 缓存stream  便于重复利用 减少GC压力
        New: func() interface{} {
            return NewStream(api, nil, 512)
        },
    }
    api.iteratorPool = &sync.Pool{                 // 缓存iterator 便于重复利用 减少GC压力
        New: func() interface{} {
            return NewIterator(api)
        },
    }
    api.initCache()                                // 编码和解码本地缓存
    encoderExtension := EncoderExtension{}
    decoderExtension := DecoderExtension{}
    if cfg.MarshalFloatWith6Digits {                 // 添加扩展选项的内容
        api.marshalFloatWith6Digits(encoderExtension)
    }
    if cfg.EscapeHTML {
        api.escapeHTML(encoderExtension)
    }
    if cfg.UseNumber {
        api.useNumber(decoderExtension)
    }
    if cfg.ValidateJsonRawMessage {
        api.validateJsonRawMessage(encoderExtension)
    }
    api.encoderExtension = encoderExtension
    api.decoderExtension = decoderExtension
    api.configBeforeFrozen = cfg
    return api
}

2.真正执行Marshal操作:frozenConfig.Marshal(XXX),先来看下源码

func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {  // 序列化
   stream := cfg.BorrowStream(nil)          // 复用Stream
   defer cfg.ReturnStream(stream)          // 回收stream
   stream.WriteVal(v)                               // 真正执行具体的操作,在下面我们会深入分析,涉及内容比较多
   if stream.Error != nil {
       return nil, stream.Error
   }
   result := stream.Buffer()                 // 通过将stream对应的[]byte赋值到临时[]byte 便于stream进行回收到Pool中
   copied := make([]byte, len(result))
   copy(copied, result)                      // 将stream关联的[]byte 拷贝到临时[]byte中
   return copied, nil
}
1、reflect.go中的EncoderOf
func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder {
    cacheKey := typ.RType()                                              // 根据reflect2.Type类型获取对应的cache key
    encoder := cfg.getEncoderFromCache(cacheKey)         
    if encoder != nil {                                                           // 获取cache中的encoder
        return encoder
    }
    ctx := &ctx{                                                                   // 本地cache不存在对应的编码器encoder 需要新建
        frozenConfig: cfg,
        prefix:       "",
        decoders:     map[reflect2.Type]ValDecoder{},
        encoders:     map[reflect2.Type]ValEncoder{},
    }
    encoder = encoderOfType(ctx, typ)                  // 根据ctx和type创建编码器encoder
    if typ.LikePtr() {                                                 // 该类型类似指针 需要通过onePtrEncoder进行包装
        encoder = &onePtrEncoder{encoder}
    }
    cfg.addEncoderToCache(cacheKey, encoder)  // 新建的编码器encoder放入本地缓存
    return encoder
}
2、reflect.go中的encoderOfType
func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
    encoder := getTypeEncoderFromExtension(ctx, typ)             // 从扩展的编码器encoder:extensions中获取encoder
    if encoder != nil {
        return encoder
    }
    encoder = createEncoderOfType(ctx, typ)                      // 扩展编码器中不存在对应类型的编码器 需要新建
    for _, extension := range extensions {
        encoder = extension.DecorateEncoder(typ, encoder)
    }
    encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder)
    for _, extension := range ctx.extraExtensions {
        encoder = extension.DecorateEncoder(typ, encoder)
    }
    return encoder
}
// 真正完成对应类型Type的编码器Encoder创建
func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
    encoder := ctx.encoders[typ]
    if encoder != nil {
        return encoder
    }
    placeholder := &placeholderEncoder{}
    ctx.encoders[typ] = placeholder
    encoder = _createEncoderOfType(ctx, typ)
    placeholder.encoder = encoder
    return encoder
}
func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
    encoder := createEncoderOfJsonRawMessage(ctx, typ)
    if encoder != nil {
        return encoder
    }
    encoder = createEncoderOfJsonNumber(ctx, typ)
    if encoder != nil {
        return encoder
    }
    encoder = createEncoderOfMarshaler(ctx, typ)
    if encoder != nil {
        return encoder
    }
    encoder = createEncoderOfAny(ctx, typ)
    if encoder != nil {
        return encoder
    }
    encoder = createEncoderOfNative(ctx, typ)
    if encoder != nil {
        return encoder
    }
    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())}
    }
}
上一篇下一篇

猜你喜欢

热点阅读