Go 语言中的 JSON 处理:实战解析与序列化
JSON (JavaScript Object Notation) 是 Web 开发中最流行的数据交换格式之一。在 Go (Golang) 语言中,通过标准包 encoding/json 实现 JSON 处理,该包提供了强大且便捷的工具,用于序列化(将数据结构转换为 JSON)和反序列化(将 JSON 解析为 Go 结构体)。本文将通过实际示例,详细讲解如何在 Go 中处理 JSON。
基础:将结构体序列化为 JSON
在 Go 中处理 JSON 最常见的方式是使用带有标签的结构体。标签允许指定 JSON 中的字段名称,这些名称可以与 Go 中的字段名称不同。来看一个基本的序列化示例:
package main
import ( "encoding/json" "fmt")
type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` IsActive bool `json:"is_active"`}
func main() { user := User{ ID: 1, Name: "伊万·彼得罗夫", Email: "ivan@example.com", IsActive: true, }
jsonData, err := json.Marshal(user) if err != nil { fmt.Println("序列化错误:", err) return }
fmt.Println(string(jsonData)) // 输出: {"id":1,"name":"伊万·彼得罗夫","email":"ivan@example.com","is_active":true}}请注意:我们使用 json:"字段名" 标签来控制 JSON 中的键名。当需要遵循特定的命名规范时(例如 JSON 中使用 snake_case,Go 中使用 CamelCase),这尤其方便。
将 JSON 解析为 Go 结构体
使用 json.Unmarshal 函数可以将 JSON 数据反序列化(解析)为结构体。重要的是,结构体必须与 JSON 对象的结构相匹配。继续我们的示例:
func main() { jsonString := `{"id":2,"name":"玛丽亚·西多罗娃","email":"maria@example.com","is_active":false}`
var user User err := json.Unmarshal([]byte(jsonString), &user) if err != nil { fmt.Println("解析错误:", err) return }
fmt.Printf("ID: %d, Name: %s, Email: %s, Active: %t", user.ID, user.Name, user.Email, user.IsActive) // 输出: ID: 2, Name: 玛丽亚·西多罗娃, Email: maria@example.com, Active: false}重要提示: 必须始终将结构体的指针(&user)传递给 json.Unmarshal 函数,否则修改将不会被保存。
处理嵌套结构和数组
实际的 JSON 数据通常包含嵌套对象和数组。Go 可以通过嵌套结构体优雅地处理这些情况:
type Address struct { City string `json:"city"` Street string `json:"street"` ZipCode string `json:"zip_code"`}
type Employee struct { ID int `json:"id"` Name string `json:"name"` Skills []string `json:"skills"` Address Address `json:"address"`}
func main() { jsonData := `{ "id": 101, "name": "阿列克谢·伊万诺夫", "skills": ["Go", "Python", "Docker"], "address": { "city": "莫斯科", "street": "特维尔大街, 10", "zip_code": "101000" } }`
var emp Employee err := json.Unmarshal([]byte(jsonData), &emp) if err != nil { fmt.Println("错误:", err) return }
fmt.Printf("员工: %s, 城市: %s, 技能: %v", emp.Name, emp.Address.City, emp.Skills) // 输出: 员工: 阿列克谢·伊万诺夫, 城市: 莫斯科, 技能: [Go Python Docker]}在 Go 中,数组使用切片([]string),而嵌套对象则使用单独的结构体。当解析对象数组时,可以