JSON 是目前最为流行的序列化手段,Go 语言内置 encoding/json 包用于 JSON 序列化 / 反序列化 操作。本文以详细代码示例,演示 encoding/json 包的使用方式。
序列化
对于已有类型,序列化只需一行代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package main
import (
"encoding/json"
"fmt"
"log"
)
type Pair struct {
Name string
Value int
}
func main() {
pair := Pair{
Name: "bar",
Value: 1,
}
content, err := json.Marshal(pair)
if err == nil {
fmt.Printf("%s\n", content)
} else {
log.Fatal(pair)
}
}
|
例子第 9~12 行,定义了一个 Pair 类型,包含两个字段;第 15~18 行,定义了一个 Pair 变量并初始化;第 20 行对该变量进行 JSON 序列化操作,结果如下:
1
|
{"Name":"bar","Value":1}
|
静态序列化
为了生成 JSON 数据,如果类型未定义,则需要先定义新的数据类型。
例如,为了临时生成以下两种不同格式的 JSON 数据:
1
2
|
{"Type":"map","Data":{"Bar":1,"Foo":2}}
{"Type":"list","Data":[{"Name":"Bar","Value":1},{"Name":"Foo","Value":2}]}
|
可以先定义以下数据类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
type Pair struct {
Name string
Value int
}
type Map struct {
Bar int
Foo int
}
type Message struct {
Type string
Data Object
}
|
然后,初始化数据并序列化:
1
2
3
4
5
6
7
|
content, err := json.Marshal(Message{
Type: "map",
Data: Map{
Bar: 1,
Foo: 2,
},
})
|
这便是 静态序列化 方式,为了生成 JSON 数据而定义新的数据类型,好比用牛刀杀鸡。 接着,在 动态序列化 一节,介绍一种灵活构建 JSON 数据的方法,更加简便。
自定义字段
序列化结构体,字段名默认与结构体一致。 结构体字段名通过首字母大小写控制访问,因此有时并不满足需要。 例如,结构体中的字段名是驼峰风格,而 JSON 字段名却要求用小写字母以及下划线…… 这时,只能为结构体字段打上辅助标签:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
type Pair struct {
Name string `json:"name"`
Value int `json:"value"`
}
type Map struct {
Bar int `json:"bar"`
Foo int `json:"value"`
}
type Message struct {
Type string `json:"type"`
Data Object `json:"data"`
}
|
这样一来,序列化结果便满足要求了:
1
2
|
{"type":"map","data":{"bar":1,"value":2}}
{"type":"list","data":[{"name":"Bar","value":1},{"name":"Foo","value":2}]}
|
动态序列化
像 Python 之类的动态类型语言,我们可以非常自由地组织数据,随时随地:
1
2
3
4
5
6
7
|
json.dumps({
"type": "map",
"data": {
"bar": 1,
"foo": 2,
},
})
|
然而, Go 不是动态类型语言,是不是就没有办法实现动态序列化了呢?
当然不是了,我们可以通过空接口实现。 首先定义几种基本类型:
1
2
3
4
5
|
type Object interface {}
type Array []Object
type JsonObject map[string]Object
type JsonArray Array
|
其中,Object 可以是任意类型;Array 可以是任意类型组成的 数组 ;JsonOject 是一个 映射表 ,键为字符类型,值可以是任意类型;JsonArray 与 Array 相同。
有了这些基本类型,我们也可以非常灵活的组装数据,同样随时随地:
1
2
3
4
5
6
7
|
content, err := json.Marshal(JsonObject{
"type": "map",
"data": JsonObject{
"bar": 1,
"foo": 2,
},
})
|
组装另一种数据类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
content, err = json.Marshal(JsonObject{
"type": "list",
"data": Array{
JsonObject{
"name": "bar",
"value": 1,
},
JsonObject{
"name": "foo",
"value": 2,
},
},
})
|
【小菜学Go语言】系列文章首发于公众号【小菜学编程】,敬请关注: