模块 8 · 第 5 课(共 5)课程中的40/50~14 min
模块课程(5/5)
`编码/json`
encoding/json 是用于将 Go 结构序列化为 JSON 并返回的规范包。了解其约定和陷阱可以帮助您节省在 API 和配置文件上进行调试的时间。
元帅和元帅
两个主要功能:
Go
data, err := json.Marshal(v) // Go → []byte JSON
err = json.Unmarshal(data, &v) // JSON → Go (pass a pointer!)Go
type User struct {
Name string
Email string
}
u := User{Name: "Ada", Email: "ada@example.com"}
b, _ := json.Marshal(u)
fmt.Println(string(b))
// {"Name":"Ada","Email":"ada@example.com"}
var back User
_ = json.Unmarshal(b, &back)对于缩进输出(人类可读),请使用 json.MarshalIndent(v, "", " ")。
仅导出字段
json.Marshal 仅序列化导出字段(大写)。私有字段被默默地忽略:
Go
type U struct {
Name string // exported → serialized
age int // private → ignored
}结构标签:控制名称和选项
json:"..." 标签控制输出中的名称、省略和类型:
Go
type User struct {
Name string `json:"name"` // rename
Email string `json:"email,omitempty"` // omit if zero value
Private string `json:"-"` // never serialized
ID int `json:"id,string"` // number as string
}最常用的选项:
,omitempty— 如果该字段是零值(0、“”、nil、空切片/映射),则忽略该字段。,-— 从未序列化/反序列化。,string— 将数字/布尔值包装为字符串(对于 JS ID 有用)。
流的解码器/编码器
使用 io.Reader/io.Writer (HTTP 正文、大文件)时,使用 Decoder 和 Encoder 而不是加载内存中的所有内容:
Go
dec := json.NewDecoder(resp.Body)
var users []User
if err := dec.Decode(&users); err != nil {
return err
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
_ = enc.Encode(users)Decoder 还支持 dec.Token() 进行流式逐段解析,并支持 dec.DisallowUnknownFields() 拒绝带有意外键的 JSON(对于输入验证有用)。
通用地图和 any
如果您不知道架构,请反序列化为 map[string]any:
Go
var v map[string]any
_ = json.Unmarshal(data, &v)
fmt.Println(v["name"])值将具有动态类型(数字为 string、float64,[]any、map[string]any、bool、nil)。
常见错误
- 忘记
&:json.Unmarshal(data, v)不会填充任何内容;你需要&v。 - 使用 nil 字段解码结构:为了避免恐慌,请在读取字段之前检查
err。 - 不兼容的类型:将数字反序列化为字符串,反之亦然,返回
*json.UnmarshalTypeError。
练习
锻炼#go.m8.l5.e1
尝试:0加载中...
使用 json.Marshal 将 struct u 序列化为 JSON,并将结果打印为字符串。
正在加载编辑器...
3 次尝试后可用的解决方案
锻炼#go.m8.l5.e2
尝试:0加载中...
使用 json.Unmarshal 将 `{"Name":"Ada"}` 反序列化为 struct U 并打印它。
正在加载编辑器...
3 次尝试后可用的解决方案
Quiz#go.m8.l5.e3
准备好json.Marshal 是否包含结构体的字段“name string”(小写)?
Go
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))