golang json 包简单分析
2015-09-24 15:17
555 查看
首先上代码:
输出:
以最简单的单个bool 类型的序列化为例,我们来搞清楚json 包里面的调用栈如下:
从入口出发,第一个方法是:
这里没有什么特殊,只是为了引出encodeState
这里的Buffer就是我们所有输出字节的Buffer,再继续往里面走
这里我们看到了反射获得值,个人认为这里的命名不太科学,不过无妨,继续往下走。
这里通过反射的类型,获得和使用该类型的序列化方法.顺便还做了把缓存。
至于具体的Encoder,通过Type很容易找到。
最终我们这里的boolEncoder的实现
当然这个只是一个最简单的示例,里面很多实现的细节可以推敲。这里只是把这种序列化的方式归结为类型反射+缓存的方式。
func main() { b := true a1, _ := json.Marshal(b) a2, _ := Marshal(b) fmt.Println(string(a1)) fmt.Println(string(a2))}
输出:
truetrue
以最简单的单个bool 类型的序列化为例,我们来搞清楚json 包里面的调用栈如下:
从入口出发,第一个方法是:
func Marshal(v interface{}) ([]byte, error) { e := &encodeState{} err := e.marshal(v) if err != nil { return nil, err } return e.Bytes(), nil}
这里没有什么特殊,只是为了引出encodeState
// An encodeState encodes JSON into a bytes.Buffer.type encodeState struct { bytes.Buffer // accumulated output scratch [64]byte}
这里的Buffer就是我们所有输出字节的Buffer,再继续往里面走
func (e *encodeState) marshal(v interface{}) (err error) { defer func() { if r := recover(); r != nil { if _, ok := r.(runtime.Error); ok { panic(r) } if s, ok := r.(string); ok { panic(s) } err = r.(error) } }() e.reflectValue(reflect.ValueOf(v)) return nil}
这里我们看到了反射获得值,个人认为这里的命名不太科学,不过无妨,继续往下走。
func valueEncoder(v reflect.Value) encoderFunc { if !v.IsValid() { return invalidValueEncoder } return typeEncoder(v.Type())}
这里通过反射的类型,获得和使用该类型的序列化方法.顺便还做了把缓存。
func typeEncoder(t reflect.Type) encoderFunc { encoderCache.RLock() f := encoderCache.m[t] encoderCache.RUnlock() if f != nil { return f } // To deal with recursive types, populate the map with an // indirect func before we build it. This type waits on the // real func (f) to be ready and then calls it. This indirect // func is only used for recursive types. encoderCache.Lock() if encoderCache.m == nil { encoderCache.m = make(map[reflect.Type]encoderFunc) } var wg sync.WaitGroup wg.Add(1) encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) { wg.Wait() f(e, v, quoted) } encoderCache.Unlock() // Compute fields without lock. // Might duplicate effort but won't hold other computations back. f = newTypeEncoder(t, true) wg.Done() encoderCache.Lock() encoderCache.m[t] = f encoderCache.Unlock() return f}
至于具体的Encoder,通过Type很容易找到。
switch t.Kind() { case reflect.Bool: return boolEncoder case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return intEncoder case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return uintEncoder case reflect.Float32: return float32Encoder case reflect.Float64: return float64Encoder case reflect.String: return stringEncoder case reflect.Interface: return interfaceEncoder case reflect.Struct: return newStructEncoder(t) case reflect.Map: return newMapEncoder(t) case reflect.Slice: return newSliceEncoder(t) case reflect.Array: return newArrayEncoder(t) case reflect.Ptr: return newPtrEncoder(t) default: return unsupportedTypeEncoder
最终我们这里的boolEncoder的实现
func boolEncoder(e *encodeState, v reflect.Value, quoted bool) { if quoted { e.WriteByte('"') } if v.Bool() { e.WriteString("true") } else { e.WriteString("false") } if quoted { e.WriteByte('"') }}
当然这个只是一个最简单的示例,里面很多实现的细节可以推敲。这里只是把这种序列化的方式归结为类型反射+缓存的方式。
备注
这个系列不是一个大而全的package api 指南,只包括作者认为最常见的使用方式。抗议无效。相关文章推荐
- js弹出框、对话框、提示框、弹窗总结 .
- js日期处理
- javascript获取select值,树形随着select值的变化而变化
- JS实现滑动菜单效果代码(包括Tab,选项卡,横向等效果)
- js map
- js实现收藏网址
- jstl根据字符串进行判断
- json序列化反序列化插件-json2.js 介绍和使用
- javaScript里的正则表达式RegExp和replace
- js点击某个图标或按钮弹出文件选择框
- JS弹出窗口
- 详解js闭包
- PageInfo 前台分页js,带分页栏
- 详解JavaScript Document对象
- 关于jstl标签
- js判断日期大小
- JavaScript删除数组重复元素的5个高效算法
- JavaScript异步编程的4种方法
- JavaScript:函数与对象的关系
- URL请求并解析JSON数据