跳转到主要内容
模块 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))
答案选项