@aliasliyu4
2016-12-15T15:55:05.000000Z
字数 3472
阅读 6493
json是在开发当中一种常见的数据结构,本身它的协议栈就是很简洁的,如果有兴趣的同学,可以参考RFC4627文档,本文的最后我会附上这部分的链接,方便大家查看。那么在go项目的开发当中,比如最常见的web项目,我们需用到json来传递数据,那么必然就会面对将json object,转换成go中对应的数据结构的需求。无需担心的是,go提供了encoding/json解析包,我们接下来要做的工作就是在此基础上做一定封装,以方便自己使用。同时这个库也是特别适合新手来练手使用,因为它设计到了go中的map,struct,assert,interface{}...,所以对于加深对go基础的理解也很有帮助,甚至你还可以写出更好的呢!
项目地址: https://github.com/liyu4/ljson
定义一个全局对象,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 = f
return j
}
获取map,这里我们使用了断言,判断interface{}是否是map[string]interface{}类型
// return map in Go
func (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 object
func (j *Js) Get(key string) *Js {
m := j.GetMapData()
if v, ok := m[key]; ok {
j.data = v
return j
}
j.data = nil
return j
}
或者value根据下标,这里指的是从slice和map中,你懂的,这里有一个点需要小心一下,就是map返回的顺序是不固定的
// GetIndex get []interface or map in Go
func (j *Js) GetIndex(i int) *Js {
num := i - 1
if 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 = 0
var 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 = data
return j
case string:
data[i] = vv
j.data = data
return j
case []interface{}:
j.data = vv
return j
}
}
n++
}
}
}
j.data = nil
return j
}
自定义key和下标返回value,注意错误的处理
// The data must be []interface{}, According to your custom number to return key adn array data
func (j *Js) GetKey(key string, i int) (*Js, error) {
num := i - 1
if 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 = h
return j, nil
}
}
j.data = nil
return j, nil
}
递归map
// According to the custom of the PATH to fing element
// You can use function this to find recursive map
func (j *Js) GetPath(args ...string) *Js {
d := j
for i := range args {
m := d.GetMapData()
if val, ok := m[args[i]]; ok {
d.data = val
} else {
d.data = nil
return d
}
}
return d
}
String方法,相信大家也看到了我们的slice和map中的值都是interface{},转换陈string能方便我们的操作。
// String return string
func (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 []string
if 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 array
func (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 test
func (j *Js) Type() {
fmt.Println(reflect.TypeOf(j.data))
}
至此我们就完成了一个可以部署在生产环境中的json library,这个项目是小巧和坚实的,希望大家能自己动手写写,最好是在下雨的星期天下午。