Go 自定义 Json 序列化规则

1. 什么是 Json 序列化

在计算机科学中,序列化是将数据结构或对象转换为可存储或传输格式的过程。反序列化则是将已序列化的数据还原回其原始格式的过程。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,通常用于客户端和服务器之间的数据传输。Go语言中的标准库中提供了对 JSON 的编码解码支持,但是有时候我们需要自定义 JSON 的序列化规则,以满足我们的特定需求。

2. Go 自定义 Json 序列化规则

2.1 自定义字段的 JSON 名称

在 Go 中,可以通过在字段或方法上加上 `json:""` 标签的方式来自定义 JSON 的名称。例如,我们有如下定义:

type User struct {

FirstName string `json:"first_name"`

LastName string `json:"last_name"`

}

这样,在进行 JSON 编码的时候,将会使用 `first_name` 和 `last_name` 来作为 JSON 对象的属性名:

u := User{FirstName: "John", LastName: "Doe"}

jsonData, err := json.Marshal(u)

fmt.Println(string(jsonData)) // {"first_name":"John","last_name":"Doe"}

2.2 在序列化时忽略字段

有时候,我们希望某些字段在进行 JSON 编码时被忽略掉,这时可以在该字段上加上 `json:"-"` 标签。例如:

type User2 struct {

FirstName string `json:"first_name"`

LastName string `json:"-"`

}

这样,在进行 JSON 编码的时候,将会忽略 `last_name` 字段,生成的 JSON 对象中只包含 `first_name` 字段:

u2 := User2{FirstName: "John", LastName: "Doe"}

jsonData, err := json.Marshal(u2)

fmt.Println(string(jsonData)) // {"first_name":"John"}

2.3 在序列化时添加额外字段

有时候,我们需要在进行 JSON 编码时添加一些额外的字段,这时可以定义一个自定义类型,然后在该类型上定义一个 `MarshalJSON` 方法以实现定制的 JSON 序列化。例如:

type User3 struct {

FirstName string

LastName string

}

type User3JSON struct {

*User3

FullName string `json:"full_name"`

}

func (u *User3) MarshalJSON() ([]byte, error) {

return json.Marshal(&User3JSON{

User3: u,

FullName: u.FirstName + " " + u.LastName,

})

}

这样,在进行 JSON 编码时会调用 `MarshalJSON` 方法,生成的 JSON 对象将会包含 `full_name` 字段:

u3 := User3{FirstName: "John", LastName: "Doe"}

jsonData, err := json.Marshal(u3)

fmt.Println(string(jsonData)) // {"full_name":"John Doe","FirstName":"John","LastName":"Doe"}

2.4 在序列化时处理时间

在进行 JSON 序列化时,需要特别注意处理时间类型的字段。在 Go 中,时间类型的字段默认使用 RFC3339 格式进行序列化。例如:

type Post struct {

Title string `json:"title"`

Body string `json:"body"`

CreatedAt time.Time `json:"created_at"`

}

post := Post{

Title: "Hello, World!",

Body: "This is my first post.",

CreatedAt: time.Now(),

}

jsonData, err := json.Marshal(post)

fmt.Println(string(jsonData))

输出结果如下:

{

"title": "Hello, World!",

"body": "This is my first post.",

"created_at": "2022-03-01T14:23:33.93839+08:00"

}

可以看到,时间类型的字段被序列化成了字符串。但是,有时候我们需要将时间序列化成指定的格式,或者进行时区转换等操作。这时,可以使用 `Marshaler` 和 `Unmarshaler` 接口来实现自定义序列化和反序列化逻辑。

例如,我们希望在进行 JSON 序列化时,将时间格式化为指定的字符串格式,可以定义如下类型:

type Post2 struct {

Title string `json:"title"`

Body string `json:"body"`

CreatedAt time.Time `json:"created_at"`

}

func (p *Post2) MarshalJSON() ([]byte, error) {

type Alias Post2

return json.Marshal(&struct {

*Alias

CreatedAt string `json:"created_at"`

}{

Alias: (*Alias)(p),

CreatedAt: p.CreatedAt.Format("2006-01-02 15:04:05"),

})

}

这里定义了一个 `MarshalJSON` 方法,使用 `type Alias` 来避免递归。在方法中定义了一个新的结构体,并在其中包含了 `Post2` 类型的所有字段,并额外添加了一个 `CreatedAt` 字段,用于存储格式化后的时间字符串。在最后,再调用 `json.Marshal` 对新的结构体进行序列化。这样,在进行 JSON 序列化时,就会调用 `MarshalJSON` 方法,将时间类型序列化成我们指定的格式:

post2 := Post2{

Title: "Hello, World!",

Body: "This is my first post.",

CreatedAt: time.Now(),

}

jsonData, err := json.Marshal(post2)

fmt.Println(string(jsonData))

输出结果如下:

{

"title": "Hello, World!",

"body": "This is my first post.",

"created_at": "2022-03-01 14:23:33"

}

2.5 总结

本文介绍了 Go 中自定义 JSON 序列化规则的方法,包括自定义字段的 JSON 名称、在序列化时忽略字段、在序列化时添加额外字段和在序列化时处理时间。对于需要定制 JSON 序列化的应用场景,这些方法可以帮助我们更灵活地处理数据。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签