JSON(JavaScript Object Notation)是一种常见的数据交换格式。Go 标准库提供了
encoding/json
包,用于方便地将结构体与 JSON 之间互转。
一、序列化(Marshal)
将 Go 中的数据结构(如结构体、map、slice 等)转换为 JSON 字符串,称为“序列化”。
1. 基本示例:
package main import ( "encoding/json" "fmt" ) type Person struct { Name string Age int } func main() { p := Person{Name: "Tom", Age: 30} data, _ := json.Marshal(p) fmt.Println(string(data)) // 输出:{"Name":"Tom","Age":30} }
二、反序列化(Unmarshal)
将 JSON 字符串转换为 Go 数据结构的过程,称为“反序列化”。
示例:
jsonStr := `{"Name":"Alice","Age":25}` var p Person json.Unmarshal([]byte(jsonStr), &p) fmt.Println(p.Name, p.Age) // 输出:Alice 25
三、结构体字段标签(Tag)
Go 的 json
标签用于控制字段与 JSON 键之间的映射。
type Person struct { Name string `json:"name"` // 指定键为 name Age int `json:"age"` }
输出示例:
p := Person{Name: "Tom", Age: 20} data, _ := json.Marshal(p) fmt.Println(string(data)) // {"name":"Tom","age":20}
四、控制字段行为的标签
标签形式 | 含义 |
json:"name" |
重命名字段为 name |
json:"name,omitempty" |
若字段值为空则忽略 |
json:"-" |
忽略该字段,不进行序列化/反序列化 |
示例:
type User struct { Name string `json:"name"` Token string `json:"-"` // 忽略 Age int `json:"age,omitempty"` // 0 则不输出 }
五、处理 map 和切片
data := map[string]interface{}{ "name": "Go", "year": 2009, } bytes, _ := json.Marshal(data) fmt.Println(string(bytes)) // {"name":"Go","year":2009}
六、嵌套结构体序列化
type Address struct { City string `json:"city"` State string `json:"state"` } type User struct { Name string `json:"name"` Address Address `json:"address"` }
序列化会生成嵌套的 JSON 结构:
{ "name": "Bob", "address": { "city": "Beijing", "state": "CN" } }
七、反序列化未知结构(使用 map[string]interface{}
)
str := `{"name":"Go","version":1.18}` var result map[string]interface{} json.Unmarshal([]byte(str), &result) fmt.Println(result["name"]) // Go fmt.Println(result["version"].(float64)) // 1.18
注意:数字默认会被解析为 float64
。
八、处理 JSON 数组
jsonStr := `[{"name":"Tom"},{"name":"Jerry"}]` var users []map[string]string json.Unmarshal([]byte(jsonStr), &users) fmt.Println(users[0]["name"]) // Tom
九、小结
功能 | 方法名 | 类型要求 |
序列化 | json.Marshal() |
输入:结构体/map/slice |
反序列化 | json.Unmarshal() |
输出:指针(结构体/map) |