diff --git a/zh/07.2.md b/zh/07.2.md index 5f0cbbb3..8cd00de8 100644 --- a/zh/07.2.md +++ b/zh/07.2.md @@ -4,7 +4,7 @@ JSON(Javascript Object Notation)是一种轻量级的数据交换语言, 前一小节的运维的例子用json来表示,结果描述如下: ```json - {"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]} +{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]} ``` 本小节余下的内容将以此JSON数据为基础,来介绍go语言的json包对JSON数据的编、解码。 ## 解析JSON @@ -13,33 +13,33 @@ JSON(Javascript Object Notation)是一种轻量级的数据交换语言, 假如有了上面的JSON串,那么我们如何来解析这个JSON串呢?Go的JSON包中有如下函数 ```Go - func Unmarshal(data []byte, v interface{}) error +func Unmarshal(data []byte, v interface{}) error ``` 通过这个函数我们就可以实现解析的目的,详细的解析例子请看如下代码: ```Go - package main +package main - import ( - "encoding/json" - "fmt" - ) +import ( + "encoding/json" + "fmt" +) - type Server struct { - ServerName string - ServerIP string - } +type Server struct { + ServerName string + ServerIP string +} - type Serverslice struct { - Servers []Server - } +type Serverslice struct { + Servers []Server +} - func main() { - var s Serverslice - str := `{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}` - json.Unmarshal([]byte(str), &s) - fmt.Println(s) - } +func main() { + var s Serverslice + str := `{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}` + json.Unmarshal([]byte(str), &s) + fmt.Println(s) +} ``` 在上面的示例代码中,我们首先定义了与json数据对应的结构体,数组对应slice,字段名对应JSON里面的KEY,在解析的时候,如何将json数据与struct字段相匹配呢?例如JSON的key是`Foo`,那么怎么找对应的字段呢? @@ -62,71 +62,71 @@ JSON(Javascript Object Notation)是一种轻量级的数据交换语言, 现在我们假设有如下的JSON数据 ```Go - b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`) +b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`) ``` 如果在我们不知道他的结构的情况下,我们把他解析到interface{}里面 ```Go - var f interface{} - err := json.Unmarshal(b, &f) +var f interface{} +err := json.Unmarshal(b, &f) ``` 这个时候f里面存储了一个map类型,他们的key是string,值存储在空的interface{}里 ```Go - f = map[string]interface{}{ - "Name": "Wednesday", - "Age": 6, - "Parents": []interface{}{ - "Gomez", - "Morticia", - }, - } +f = map[string]interface{}{ + "Name": "Wednesday", + "Age": 6, + "Parents": []interface{}{ + "Gomez", + "Morticia", + }, +} ``` 那么如何来访问这些数据呢?通过断言的方式: ```Go - m := f.(map[string]interface{}) +m := f.(map[string]interface{}) ``` 通过断言之后,你就可以通过如下方式来访问里面的数据了 ```Go - for k, v := range m { - switch vv := v.(type) { - case string: - fmt.Println(k, "is string", vv) - case int: - fmt.Println(k, "is int", vv) - case float64: - fmt.Println(k,"is float64",vv) - case []interface{}: - fmt.Println(k, "is an array:") - for i, u := range vv { - fmt.Println(i, u) - } - default: - fmt.Println(k, "is of a type I don't know how to handle") +for k, v := range m { + switch vv := v.(type) { + case string: + fmt.Println(k, "is string", vv) + case int: + fmt.Println(k, "is int", vv) + case float64: + fmt.Println(k,"is float64",vv) + case []interface{}: + fmt.Println(k, "is an array:") + for i, u := range vv { + fmt.Println(i, u) } + default: + fmt.Println(k, "is of a type I don't know how to handle") } +} ``` 通过上面的示例可以看到,通过interface{}与type assert的配合,我们就可以解析未知结构的JSON数了。 上面这个是官方提供的解决方案,其实很多时候我们通过类型断言,操作起来不是很方便,目前bitly公司开源了一个叫做`simplejson`的包,在处理未知结构体的JSON时相当方便,详细例子如下所示: ```Go - js, err := NewJson([]byte(`{ - "test": { - "array": [1, "2", 3], - "int": 10, - "float": 5.150, - "bignum": 9223372036854775807, - "string": "simplejson", - "bool": true - } - }`)) +js, err := NewJson([]byte(`{ + "test": { + "array": [1, "2", 3], + "int": 10, + "float": 5.150, + "bignum": 9223372036854775807, + "string": "simplejson", + "bool": true + } +}`)) - arr, _ := js.Get("test").Get("array").Array() - i, _ := js.Get("test").Get("int").Int() - ms := js.Get("test").Get("string").MustString() +arr, _ := js.Get("test").Get("array").Array() +i, _ := js.Get("test").Get("int").Int() +ms := js.Get("test").Get("string").MustString() ``` 可以看到,使用这个库操作JSON比起官方包来说,简单的多,详细的请参考如下地址:https://github.com/bitly/go-simplejson @@ -135,55 +135,55 @@ JSON(Javascript Object Notation)是一种轻量级的数据交换语言, 我们开发很多应用的时候,最后都是要输出JSON数据串,那么如何来处理呢?JSON包里面通过`Marshal`函数来处理,函数定义如下: ```Go - func Marshal(v interface{}) ([]byte, error) +func Marshal(v interface{}) ([]byte, error) ``` 假设我们还是需要生成上面的服务器列表信息,那么如何来处理呢?请看下面的例子: ```Go - package main +package main - import ( - "encoding/json" - "fmt" - ) +import ( + "encoding/json" + "fmt" +) - type Server struct { - ServerName string - ServerIP string - } - - type Serverslice struct { - Servers []Server - } - - func main() { - var s Serverslice - s.Servers = append(s.Servers, Server{ServerName: "Shanghai_VPN", ServerIP: "127.0.0.1"}) - s.Servers = append(s.Servers, Server{ServerName: "Beijing_VPN", ServerIP: "127.0.0.2"}) - b, err := json.Marshal(s) - if err != nil { - fmt.Println("json err:", err) - } - fmt.Println(string(b)) +type Server struct { + ServerName string + ServerIP string +} + +type Serverslice struct { + Servers []Server +} + +func main() { + var s Serverslice + s.Servers = append(s.Servers, Server{ServerName: "Shanghai_VPN", ServerIP: "127.0.0.1"}) + s.Servers = append(s.Servers, Server{ServerName: "Beijing_VPN", ServerIP: "127.0.0.2"}) + b, err := json.Marshal(s) + if err != nil { + fmt.Println("json err:", err) } + fmt.Println(string(b)) +} ``` 输出如下内容: ```json - {"Servers":[{"ServerName":"Shanghai_VPN","ServerIP":"127.0.0.1"},{"ServerName":"Beijing_VPN","ServerIP":"127.0.0.2"}]} +{"Servers":[{"ServerName":"Shanghai_VPN","ServerIP":"127.0.0.1"},{"ServerName":"Beijing_VPN","ServerIP":"127.0.0.2"}]} ``` 我们看到上面的输出字段名的首字母都是大写的,如果你想用小写的首字母怎么办呢?把结构体的字段名改成首字母小写的?JSON输出的时候必须注意,只有导出的字段才会被输出,如果修改字段名,那么就会发现什么都不会输出,所以必须通过struct tag定义来实现: ```Go - type Server struct { - ServerName string `json:"serverName"` - ServerIP string `json:"serverIP"` - } +type Server struct { + ServerName string `json:"serverName"` + ServerIP string `json:"serverIP"` +} - type Serverslice struct { - Servers []Server `json:"servers"` - } +type Serverslice struct { + Servers []Server `json:"servers"` +} ``` 通过修改上面的结构体定义,输出的JSON串就和我们最开始定义的JSON串保持一致了。 @@ -198,32 +198,32 @@ JSON(Javascript Object Notation)是一种轻量级的数据交换语言, 举例来说: ```Go - type Server struct { - // ID 不会导出到JSON中 - ID int `json:"-"` +type Server struct { + // ID 不会导出到JSON中 + ID int `json:"-"` - // ServerName2 的值会进行二次JSON编码 - ServerName string `json:"serverName"` - ServerName2 string `json:"serverName2,string"` + // ServerName2 的值会进行二次JSON编码 + ServerName string `json:"serverName"` + ServerName2 string `json:"serverName2,string"` - // 如果 ServerIP 为空,则不输出到JSON串中 - ServerIP string `json:"serverIP,omitempty"` - } + // 如果 ServerIP 为空,则不输出到JSON串中 + ServerIP string `json:"serverIP,omitempty"` +} - s := Server { - ID: 3, - ServerName: `Go "1.0" `, - ServerName2: `Go "1.0" `, - ServerIP: ``, - } - b, _ := json.Marshal(s) - os.Stdout.Write(b) +s := Server { + ID: 3, + ServerName: `Go "1.0" `, + ServerName2: `Go "1.0" `, + ServerIP: ``, +} +b, _ := json.Marshal(s) +os.Stdout.Write(b) ``` 会输出以下内容: ```json - {"serverName":"Go \"1.0\" ","serverName2":"\"Go \\\"1.0\\\" \""} +{"serverName":"Go \"1.0\" ","serverName2":"\"Go \\\"1.0\\\" \""} ``` Marshal函数只有在转换成功的时候才会返回数据,在转换的过程中我们需要注意几点: