「 json 」
提供了 JSON 与 Go 变量之间的序列化与反序列化。
📜本文内容
JSON序列化
func Marshal(v interface{}) ([]byte, error)
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
func main () {
amy := person {
Name : "Amy" ,
Country : "China" ,
City : "Beijing" ,
}
data1 , _ := json . Marshal ( amy )
fmt . Println ( string ( data1 ))
data2 , _ := json . MarshalIndent ( amy , "" , " " )
fmt . Println ( string ( data2 ))
}
使用 MarshalIndent() 可使数据输出的形式美观一些
1
2
3
4
5
6
{ "name" :"Amy" ,"country" :"China" ,"city" :"Beijing" }
{
"name" : "Amy" ,
"country" : "China" ,
"city" : "Beijing"
}
tag及使用技巧
1. 省略空字段 omitempty
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city,omitempty"`
}
func main () {
amy := person {
Name : "Amy" ,
}
data , _ := json . MarshalIndent ( amy , "" , " " )
fmt . Println ( string ( data ))
}
JSON内的 city 字段增加 omitempty 关键字,初始化对象时未对该字段赋值,在序列化后将不显示;country 字段未注明忽略空值,序列化赋了默认0值:
1
2
3
4
{
"name" : "Amy" ,
"country" : ""
}
2. 忽略特定字段 -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"-"`
}
func main () {
amy := person {
Name : "Amy" ,
Country : "China" ,
City : "Beijing" ,
}
data , _ := json . MarshalIndent ( amy , "" , " " )
fmt . Println ( string ( data ))
}
即使字段已经初始化,序列化后的内容也不会包含此字段
1
2
3
4
{
"name" : "Amy" ,
"country" : "China"
}
3. JSON字段类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Age int `json:"age,string"`
}
func main () {
amy := person {
Name : "Amy" ,
Age : 25 ,
}
data , _ := json . MarshalIndent ( amy , "" , " " )
fmt . Printf ( "%s\n\n" , string ( data ))
}
结构体内的 Age 字段为整型,加上 string 将本字段的值转化为字符串类型:
1
2
3
4
{
"name" : "Amy" ,
"age" : "25"
}
4. 临时添加新字段
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
27
28
29
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
func main () {
amy := person {
Name : "Amy" ,
Country : "China" ,
City : "Beijing" ,
}
data , _ := json . MarshalIndent (
struct {
person
Gender string `json:"gender"`
}{
person : amy ,
Gender : "female" ,
}, "" , " " )
fmt . Println ( string ( data ))
}
在序列化时新建一个结构体即可:
1
2
3
4
5
6
{
"name" : "Amy" ,
"country" : "China" ,
"city" : "Beijing" ,
"gender" : "female"
}
5. 多结构体组合成
从4中得到启发,可将多个结构体的字段组合成一个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
27
28
29
30
31
32
33
34
35
36
37
38
39
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
type occupation struct {
Company string `json:"company"`
Position string `json:"position"`
}
func main () {
amy := person {
Name : "Amy" ,
Country : "China" ,
City : "Beijing" ,
}
job := occupation {
Company : "Google" ,
Position : "developer" ,
}
data , _ := json . MarshalIndent (
struct {
person
occupation
}{
person : amy ,
occupation : job ,
}, "" , " " )
fmt . Println ( string ( data ))
}
1
2
3
4
5
6
7
{
"name" : "Amy" ,
"country" : "China" ,
"city" : "Beijing" ,
"company" : "Google" ,
"position" : "developer"
}
6. 对时间类型的序列化
Go对时间的序列化方式是格式化转化成字符串,并默认使用RFC3339标准 2006-01-02T15:04:05.999999999Z07:00 做格式化,时间对象转化为JSON默认使用 MarshalJSON() 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
func ( t Time ) MarshalJSON () ([] byte , error ) {
if y := t . Year (); y < 0 || y >= 10000 {
// RFC 3339 is clear that years are 4 digits exactly.
// See golang.org/issue/4556#c15 for more discussion.
return nil , errors . New ( "Time.MarshalJSON: year outside of range [0,9999]" )
}
b := make ([] byte , 0 , len ( RFC3339Nano ) + 2 )
b = append ( b , '"' )
b = t . AppendFormat ( b , RFC3339Nano )
b = append ( b , '"' )
return b , nil
}
Marshaler 接口定义了 MarshalJSON() 方法,Go中的时间 time.Time 实现了 Marshaler 接口:
1
2
3
type Marshaler interface {
MarshalJSON () ([] byte , error )
}
结合上述思路,我们可以自定义时间类型,实现 Marshaler 接口,达到自定义序列化的目的:
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
27
28
29
30
31
32
33
34
35
package main
import (
"encoding/json"
"fmt"
"time"
)
//自定义时间类型
type MyTime time . Time
// 实现Marshaler接口
func ( mytime MyTime ) MarshalJSON () ([] byte , error ) {
n := time . Time ( mytime ). Format ( "2006-01-02 15:04" )
t := "\"" + n + "\""
return [] byte ( t ), nil
}
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
Birthday MyTime `json:"birthday"`
}
func main () {
amy := person {
Name : "Amy" ,
Country : "China" ,
City : "Beijing" ,
Birthday : MyTime ( time . Now ()),
}
data , _ := json . MarshalIndent ( amy , "" , " " )
fmt . Println ( string ( data ))
}
本例将时间输出格式修改为 年-月-日 时:分
1
2
3
4
5
6
{
"name" : "Amy" ,
"country" : "China" ,
"city" : "Beijing" ,
"birthday" : "2019-09-05 18:42"
}
JSON反序列化
func Unmarshal(data []byte, v interface{}) error
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
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
func main () {
data := `{
"name": "Amy",
"country": "China",
"city":"Beijing"
}`
amy := person {}
err := json . Unmarshal ([] byte ( data ), & amy )
if err == nil {
fmt . Printf ( "%s\n%s\n%s\n" , amy . Name , amy . Country , amy . City )
}
}
反序列化完成字符串到对象的转化,当 Unmarshal() 方法返回错误不空表示反序列化失败
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
27
28
29
30
31
32
33
34
35
36
37
38
39
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string `json:"name"`
Country string `json:"country"`
City string `json:"city"`
}
type occupation struct {
Company string `json:"company"`
Position string `json:"position"`
}
func main () {
data := `{
"name": "Amy",
"country": "China",
"city":"Beijing",
"company":"Google",
"position":"developer"
}`
amy := person {}
job := occupation {}
err := json . Unmarshal ([] byte ( data ),
& struct {
* person
* occupation
}{ & amy , & job })
if err == nil {
fmt . Printf ( "%v\n%v\n" , amy , job )
}
}
1
2
{ Amy China Beijing}
{ Google developer}
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
27
28
29
30
31
32
33
34
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
country string `json:"country"`
}
func main () {
d := `{
"name": "Amy",
"country": "China"
}`
amy := Person {}
err := json . Unmarshal ([] byte ( d ), & amy )
if err == nil {
fmt . Printf ( "%v\n" , amy )
}
Sam := Person {
Name : "Sam" ,
country : "CN" ,
}
data , err := json . Marshal ( Sam )
if err == nil {
fmt . Printf ( "%v\n" , string ( data ))
}
}
Person
内的 country
是私有属性,JSON的序列化及反序列化都不会对私有属性转化。
👏欢迎评论👏