json是在开发当中一种常见的数据结构,本身它的协议栈就是很简洁的,如果有兴趣的同学,可以参考RFC4627文档,本文的最后我会附上这部分的链接,方便大家查看。那么在go项目的开发当中,比如最常见的web项目,我们需用到json来传递数据,那么必然就会面对将json object,转换成go中对应的数据结构的需求。无需担心的是,go提供了encoding/json解析包,我们接下来要做的工作就是在此基础上做一定封装,以方便自己使用。同时这个库也是特别适合新手来练手使用,因为它设计到了go中的map,struct,assert,interface{}...,所以对于加深对go基础的理解也很有帮助,甚至你还可以写出更好的呢!
开始
定义一个全局对象,data为interface{}类型意味这可以存储任何类型的数据。
type Js struct {data interface{}}
工厂模式实例化Js对象,这里我们将需要反序列化的data数据,先转换成byte数组, 然后将其解析到&f指向的值中,也就是说f是包含了我们反序列化得到的数据。本文接下来的部分就是对这个f的操作。
func NewJson(data string) *Js {j := new(Js)var f interface{}err := json.Unmarshal([]byte(data), &f)if nil != err {return j}j.data = freturn j}
获取map,这里我们使用了断言,判断interface{}是否是map[string]interface{}类型
// return map in Gofunc (j *Js) GetMapData() map[string]interface{} {if m, ok := (j.data).(map[string]interface{}); ok {return m}return nil}
获取key对应的value
// Acoording to the key of the returned data information , return js.data// if you know json is an objectfunc (j *Js) Get(key string) *Js {m := j.GetMapData()if v, ok := m[key]; ok {j.data = vreturn j}j.data = nilreturn j}
或者value根据下标,这里指的是从slice和map中,你懂的,这里有一个点需要小心一下,就是map返回的顺序是不固定的
// GetIndex get []interface or map in Gofunc (j *Js) GetIndex(i int) *Js {num := i - 1if m, ok := (j.data).([]interface{}); ok {if num <= len(m)-1{v := m[num]j.data = v}else{j.data = nil}return j}{if m, ok := (j.data).(map[string]interface{}); ok {var n = 0var data = make(map[string]interface{})for i, v := range m {if n == num {switch vv := v.(type) {case float64:data[i] = strconv.FormatFloat(vv, 'f', -1, 64)j.data = datareturn jcase string:data[i] = vvj.data = datareturn jcase []interface{}:j.data = vvreturn j}}n++}}}j.data = nilreturn j}
自定义key和下标返回value,注意错误的处理
// The data must be []interface{}, According to your custom number to return key adn array datafunc (j *Js) GetKey(key string, i int) (*Js, error) {num := i - 1if i > len((j.data).([]interface{})) {return nil, errors.New("index out of range list")}if m, ok := (j.data).([]interface{}); ok {v := m[num].(map[string]interface{})if h, ok := v[key]; ok {j.data = hreturn j, nil}}j.data = nilreturn j, nil}
递归map
// According to the custom of the PATH to fing element// You can use function this to find recursive mapfunc (j *Js) GetPath(args ...string) *Js {d := jfor i := range args {m := d.GetMapData()if val, ok := m[args[i]]; ok {d.data = val} else {d.data = nilreturn d}}return d}
String方法,相信大家也看到了我们的slice和map中的值都是interface{},转换陈string能方便我们的操作。
// String return stringfunc (j *Js) String() string {if m, ok := j.data.(string); ok {return m}if m, ok := j.data.(float64); ok {return strconv.FormatFloat(m, 'f', -1, 64)}return ""}
返回key和value数组 []string
func (j *Js) ToArray() (k, d []string) {var key, data []stringif m, ok := (j.data).([]interface{}); ok {for _, value := range m {for index, v := range value.(map[string]interface{}) {switch vv := v.(type) {case float64:data = append(data, strconv.FormatFloat(vv, 'f', -1, 64))key = append(key, index)case string:data = append(data, vv)key = append(key, index)}}}return key, data}if m, ok := (j.data).(map[string]interface{}); ok {for index, v := range m {switch vv := v.(type) {case float64:data = append(data, strconv.FormatFloat(vv, 'f', -1, 64))key = append(key, index)case string:data = append(data, vv)key = append(key, index)}}return key, data}return nil, nil}
返回一个[]string
// Array return arrayfunc (j *Js) Array() ([]string, error) {if a, ok := (j.data).([]interface{}); ok {array := make([]string, 0)for _, v := range a {switch vv := v.(type) {case float64:array = append(array, strconv.FormatFloat(vv, 'f', -1, 64))case string:array = append(array, vv)}}return array, nil}return nil, errors.New("type assertion to []interface{} failed")}
一个漂亮但是没啥子用的调试函数
//for testfunc (j *Js) Type() {fmt.Println(reflect.TypeOf(j.data))}
至此我们就完成了一个可以部署在生产环境中的json library,这个项目是小巧和坚实的,希望大家能自己动手写写,最好是在下雨的星期天下午。