Format and remove 07.2.md spaces
This commit is contained in:
220
zh/07.2.md
220
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函数只有在转换成功的时候才会返回数据,在转换的过程中我们需要注意几点:
|
||||
|
||||
Reference in New Issue
Block a user