Go语言的encoding/json库通过反射实现Go值与JSON互转,支持基本类型、结构体、切片、映射等,其中结构体最常用。通过结构体标签(如json:"name")可自定义JSON字段名,首字母大写的字段才能被导出。常用标签选项包括:omitempty表示零值时省略字段,-表示完全忽略字段,string表示以字符串形式编码。嵌套结构体可递归处理,匿名字段的字段会被提升至外层。反序列化时优先匹配json标签名,无标签则匹配字段原名,未定义的JSON字段默认被忽略,可通过map或自定义UnmarshalJSON捕获。实现json.Marshaler和Unmarshaler接口可自定义序列化逻辑,如格式化时间输出。掌握标签和接口定制即可灵活处理JSON。

Go语言的
encoding/json库通过反射机制将Go值与JSON数据之间相互转换。它能处理基本类型、结构体、切片、映射等,其中结构体是最常用的序列化目标。理解结构体标签(struct tags)和一些序列化技巧,能帮助你更灵活地控制JSON的输出和解析行为。
结构体标签控制JSON字段名
结构体字段可以通过
json标签自定义JSON中的键名。默认情况下,字段名会直接转为JSON键,但首字母大写字段才能被导出(序列化)。 示例:
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
序列化时,
Name字段会变成
"name",而不是
"name"。如果不写标签,会使用字段原名;如果字段名是小写(如
Name),则不会被序列化。
常用标签选项
除了指定字段名,
json标签还支持多个选项,用逗号分隔:
立即学习“go语言免费学习笔记(深入)”;
- omitempty:如果字段值为零值(如空字符串、0、nil等),则在JSON中省略该字段
- -:完全忽略该字段,不参与序列化和反序列化
- string:强制将某些类型(如数字或布尔)以字符串形式编码
type Product struct {
ID int `json:"id"`
Title string `json:"title"`
Price float64 `json:"price,omitempty"`
Secret string `json:"-"`
Count int `json:"count,string,omitempty"`
}
当
Price为0时,不会出现在JSON中。
Secret字段则完全被忽略。
Count会被编码为字符串,即使它是整数。
嵌套结构与匿名字段的处理
结构体可以嵌套,
encoding/json会递归处理。匿名字段(内嵌结构体)的字段会被“提升”到外层结构体中。 示例:
type Address struct {
City string `json:"city"`
State string `json:"state"`
}
type Person struct {
Name string `json:"name"`
Address // 匿名字段
ZipCode string `json:"zip"`
}
序列化
Person时,
City和
State会直接出现在JSON顶层,如同它们是
Person的字段。
反序列化时的字段匹配规则
反序列化时,库会根据JSON键名匹配结构体字段。匹配过程不区分标签顺序,但必须满足:
- 字段必须是导出的(首字母大写)
- 使用
json
标签优先匹配标签名 - 若无标签,则匹配字段原名
如果JSON包含结构体中不存在的字段,默认会忽略。若想捕获未知字段,可使用
map[string]interface{}或自定义UnmarshalJSON方法。
自定义序列化行为
某些类型(如时间、自定义枚举)可能需要特殊处理。实现
json.Marshaler和
json.Unmarshaler接口可控制序列化逻辑。 示例:格式化时间
type CustomTime struct {
time.Time
}
func (ct *CustomTime) MarshalJSON() ([]byte, error) {
return json.Marshal(ct.Time.Format("2006-01-02"))
}
func (ct *CustomTime) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
t, err := time.Parse("2006-01-02", s)
if err != nil {
return err
}
ct.Time = t
return nil
}
这样,时间字段可以按指定格式输出为字符串。
基本上就这些。掌握结构体标签和接口定制,就能灵活应对大多数JSON处理场景。










