Go 语言中 JSON 处理入门
JSON(JavaScript 对象表示法)是一种轻量级数据交换格式,广泛应用于 Web 应用、API 和微服务中。Go 语言(Golang)提供了强大的内置库 encoding/json,可以轻松实现数据的解析(反序列化)和序列化。在本文中,我们将深入探讨如何在 Go 中处理 JSON,涵盖主要函数、结构体以及最佳实践。
序列化与反序列化基础
序列化是将 Go 数据结构(如结构体或切片)转换为 JSON 字符串的过程。反序列化则是相反的过程——将 JSON 转换为 Go 结构体。
序列化(Marshal)
序列化使用 json.Marshal() 函数。它接收一个 Go 值,并返回包含 JSON 表示的字节切片([]byte)。
package main
import ( "encoding/json" "fmt")
type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email,omitempty"`}
func main() { user := User{Name: "Alexey", Age: 30, Email: "alex@example.com"} jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Serialization error:", err) return } fmt.Println(string(jsonData)) // Output: {"name":"Alexey","age":30,"email":"alex@example.com"}注意标签 json:"field_name"。它们允许你控制 JSON 中的键名,并添加选项,如 omitempty(如果字段为空则跳过)。
反序列化(Unmarshal)
要将 JSON 解析为 Go 结构体,使用 json.Unmarshal() 函数。它接收一个字节切片和一个指向目标结构体的指针。
func main() { jsonString := `{"name":"Maria","age":25,"email":"maria@example.com"}` var user User err := json.Unmarshal([]byte(jsonString), &user) if err != nil { fmt.Println("Parsing error:", err) return } fmt.Printf("Name: %s, Age: %d, Email: %s", user.Name, user.Age, user.Email)}重要提示:结构体必须预先定义,且其字段必须与 JSON 键名对应(考虑标签)。
处理任意 JSON 对象
有时 JSON 结构未知或过于复杂。在这种情况下,可以使用 map[string]interface{} 或 interface{}。
使用 map[string]interface{}
func main() { jsonString := `{"name":"Ivan","age":35,"address":{"city":"Moscow","street":"Lenina"}}` var result map[string]interface{} err := json.Unmarshal([]byte(jsonString), &result) if err != nil { fmt.Println("Error:", err) return } fmt.Println(result["name"]) // Ivan fmt.Println(result["age"]) // 35 (type float64) // 对于嵌套对象,需要进行类型断言 address := result["address"].(map[string]interface{}) fmt.Println(address["city"]) // Moscow}这种方法的缺点是需要手动进行类型断言(.(map[string]interface{})),如果类型不匹配,可能导致 panic。
使用 json.RawMessage
如果需要延迟解析 JSON 的一部分,可以使用 json.RawMessage。这允许你先解析主结构体,然后单独处理嵌套数据。
type Response struct { Status string `json:"status"` Data json.RawMessage `json:"data"`}
func main() { jsonString := `{"status":"ok","data":{"user":"Peter","score":100}}` var resp Response json.Unmarshal([]byte(jsonString), &resp)
// 现在可以单独解析 Data var userData map[string]interface{} json.Unm