如何将 Go struct 转换为 JSON:从新手到专家
处理 JSON 是每位 Go 后端开发者的日常工作。几乎每天你都需要向客户端发送数据、接收 API 请求或保存配置。而在 90% 的情况下,这都是 JSON。但如何将你熟悉的 struct 优雅地转换为可读的 JSON 呢?看起来很简单?然而细节决定成败:错误的标签、空字段、遗漏的错误处理——这些都会导致你的 API 返回错误的结果。
在本文中,我们将从基础到高级技巧,全面讲解 Go struct 转 JSON。你将了解标签如何工作、如何隐藏空字段、如何序列化嵌套结构体,以及如何避免因错误而出丑。让我们开始吧!
基础:encoding/json 包
Go 标准库中有一个强大的包 encoding/json。它的主要工具是 json.Marshal(用于将 struct 转换为 JSON)和 json.Unmarshal(用于反向过程)。
让我们看一个基本示例。我们有一个用户结构体:
package main
import ( "encoding/json" "fmt")
type User struct { Name string Age int Email string}
func main() { user := User{ Name: "阿列克谢", Age: 30, Email: "alex@example.com", }
jsonData, err := json.Marshal(user) if err != nil { fmt.Println("错误:", err) return }
fmt.Println(string(jsonData)) // 输出:{"Name":"阿列克谢","Age":30,"Email":"alex@example.com"}}一切正常,但有一个问题:JSON 中的键与结构体字段名相同(首字母大写)。这不符合 JSON 标准(通常使用 camelCase 或 snake_case)。
JSON 标签:控制键名
为了控制字段在 JSON 中的显示方式,可以使用 结构体标签。这些是写在字段类型后面的反引号中的特殊注解。
type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email"`}
// 现在输出将是:// {"name":"阿列克谢","age":30,"email":"alex@example.com"}标签可以解决多个问题:
- 修改字段名——使键名美观且可读
- 跳过字段——使用
json:"-"将字段完全从 JSON 中排除 - 控制空字段——
omitempty选项在字段包含零值时隐藏该字段
omitempty 的实际示例
type User struct { Name string `json:"name"` Age int `json:"age,omitempty"` Email string `json:"email,omitempty"` IsAdmin bool `json:"is_admin,omitempty"`}
func main() { user := User{Name: "玛丽亚"} jsonData, _ := json.Marshal(user) fmt.Println(string(jsonData)) // 输出:{"name":"玛丽亚"} // Age、Email 和 IsAdmin 被跳过,因为它们为空}注意:omitempty 适用于零值——0、false、空字符串、nil。这对于不需要携带多余字段的 API 非常方便。
嵌套结构体和切片
在实际项目中,数据很少是扁平的。你经常会遇到嵌套对象或数组。Go 对此处理得很好——json 包会递归处理所有字段。
type Address struct { City string `json:"city"` Street string `json:"street"` ZipCode string `json:"zip_code"`}
type Company struct { Name string `json:"name"` Address Address `json:"address"` Tags []string `json:"tags"`}
func main() { company := Company{