一、什么是JSON
JSON(JavaScript Object Notation)是一种基于文本的轻量级数据交换格式。JSON采用完全独立于语言的文本格式来描述数据,这些特性使得JSON成为理想的数据交换语言。JSON常见于前后端数据交互,也逐渐成为替代XML的数据交换格式。
二、Go语言中的JSON支持
Go语言内置json包,提供了JSON数据的编解码功能,可直接导入使用。
import "encoding/json"
三、Go结构体转JSON
Go语言中,结构体可以通过编写tag的方法来定义该结构体的JSON格式。tag位于字段的结构体定义下方,是编译器在编译时对字段进行的描述。
通过tag的方式可以自定义JSON中的每个字段名。在tag中添加一个名为`json:"<字段名>"` 的选项即可。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
person := Person{Name: "Tom", Age: 18}
jsonData, _ := json.Marshal(person)
fmt.Println(string(jsonData))
}
上述代码中,我们自定义了Person的两个字段在JSON中的名称,即`name` 和 `age`。使用json.Marshal方法,将Person结构体转换为JSON格式的字符串,输出结果如下:
{"name":"Tom","age":18}
四、结构体嵌套转换为JSON
在实际应用中,结构体通常包含多个字段,甚至是嵌套结构体。在Go语言中,同样可以通过tag的方式来定义结构体的JSON格式。
type Address struct {
Province string `json:"province"`
City string `json:"city"`
Area string `json:"area"`
Street string `json:"street"`
PostalCode string `json:"postal_code"`
}
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Address Address `json:"address"`
}
func main() {
address := Address{Province: "ZheJiang", City: "HangZhou", Area: "XiHu", Street: "WenSanLu", PostalCode: "310023"}
person := Person{Name: "Tom", Age: 18, Address: address}
jsonData, _ := json.Marshal(person)
fmt.Println(string(jsonData))
}
输出结果如下:
{"name":"Tom","age":18,"address":{"province":"ZheJiang","city":"HangZhou","area":"XiHu","street":"WenSanLu","postal_code":"310023"}}
五、切片和Map转换为JSON
除了结构体,切片和Map也经常出现在JSON编解码中。和结构体一样,切片和Map的转换也需要通过tag的方式来指定键名。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Hobbies []string `json:"hobbies"`
Metas map[string]string `json:"metas"`
}
func main() {
person := Person{
Name: "Tom",
Age: 18,
Hobbies: []string{"coding", "running", "reading"},
Metas: map[string]string{"height": "184cm", "weight": "70kg"},
}
jsonData, _ := json.Marshal(person)
fmt.Println(string(jsonData))
}
上述代码中,我们定义了一个Person结构体,并且包含了切片和Map类型的字段。使用json.Marshal方法,将Person结构体转换为JSON格式的字符串,输出结果如下:
{"name":"Tom","age":18,"hobbies":["coding","running","reading"],"metas":{"height":"184cm","weight":"70kg"}}
六、转换为JSON时的返回值
在编写代码的过程中,我们可能会需要知道json.Marshal方法转化后的返回值,该返回值有两种类型。
第一种类型为`[]byte`类型,表示将结构体转换为JSON格式后得到的字节序列。
jsonData, err := json.Marshal(person)
if err != nil {
// 错误处理
}
fmt.Println(jsonData)
第二种类型为`error`类型。当转换出错时,将返回该类型的非空值。
jsonData, err := json.Marshal(person)
if err != nil {
// 错误处理
}
fmt.Println(err)
七、从JSON转换为Go结构体
在实际开发中,还经常会遇到从JSON格式的字符串转换为Go结构体的需求。Go语言中提供了json包中的json.Unmarshal方法来完成该转换过程。
使用json.Unmarshal方法,我们需要声明一个目标类型的指针,并调用json.Unmarshal方法来实现JSON格式字符串到指定类型的转换。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
jsonStr := `{"name":"Tom","age":18}`
person := Person{}
err := json.Unmarshal([]byte(jsonStr), &person)
if err != nil {
// 错误处理
}
fmt.Printf("%+v", person)
}
上述代码中,我们声明了一个Person结构体的指针变量`person`作为目标类型,并使用json.Unmarshal方法将JSON字符串转换为结构体实例。输出转换后的Person对象,输出结果如下:
{Name:"Tom", Age:18}
八、小结
Go语言内置的json包提供了完善的JSON编解码功能,并且可以通过自定义tag的方式很容易地定义结构体的JSON格式。在实际开发中,我们需要熟练地掌握JSON转换的API以及tag的定义方法。同时,我们需要考虑到各种数据的可能性,避免出现一些JSON转换的异常状况。