Go (Golang) 中的 JSON 处理:完整指南
Go (Golang) 是一种由 Google 开发的现代编译型编程语言。其优势之一是通过标准包 encoding/json 内置了对 JSON 格式的支持。与许多其他需要安装第三方库的语言不同,Go 中的 JSON 处理“开箱即用”,并且具有高性能和强类型的特点。
在本文中,我们将详细讨论 Go 中 JSON 处理的所有方面:从简单的解析到涉及自定义类型和流式处理的复杂场景。
基础:JSON 编码与解码
encoding/json 包提供了两个主要函数:json.Marshal() 用于将 Go 结构体序列化为 JSON,以及 json.Unmarshal() 用于将 JSON 反序列化回结构体。
示例:将结构体序列化为 JSON
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: "伊万·彼得罗夫", Age: 30, Email: "ivan@example.com", }
jsonData, err := json.Marshal(user) if err != nil { fmt.Println("序列化错误:", err) return }
fmt.Println(string(jsonData)) // 输出: {"name":"伊万·彼得罗夫","age":30,"email":"ivan@example.com"}}示例:将 JSON 反序列化为结构体
func main() { jsonString := `{"name":"安娜·斯米尔诺娃","age":25,"email":"anna@example.com"}` var user User err := json.Unmarshal([]byte(jsonString), &user) if err != nil { fmt.Println("反序列化错误:", err) return }
fmt.Printf("姓名: %s, 年龄: %d, 邮箱: %s", user.Name, user.Age, user.Email)}结构体标签 (Struct Tags)
Go 中的结构体标签允许控制字段如何序列化为 JSON。这是一种强大的机制,用于配置字段名称、跳过空值以及其他选项。
标签的主要选项:
json:"name"— 设置 JSON 中的字段名称json:"-"— 完全从 JSON 中排除该字段json:"name,omitempty"— 如果字段包含零值(0, "", false, nil),则跳过该字段json:"name,string"— 强制将数字字段转换为字符串
使用不同标签的示例:
type Product struct { ID int `json:"id"` Title string `json:"title"` Description string `json:"description,omitempty"` Price float64 `json:"price,string"` SecretKey string `json:"-"`}
func main() { product := Product{ ID: 101, Title: "笔记本电脑", Description: "", Price: 899.99, SecretKey: "sk-12345", }
jsonData, _ := json.MarshalIndent(product, "", " ") fmt.Println(string(jsonData)) // 输出: // { // "id": 101, // "title": "笔记本电脑", // "price": "899.99" // }}处理任意 JSON 数据 (interface{})
有时 JSON 数据的结构事先未知。在这种情况下,可以使用 interface{} 或 map[string]interface{} 类型。
func main() { jsonString := `{"name":"测试","values":[1,2,3],"active":true,"metadata":{"version":2}}` var data map[string]interface{} err := json.Unmarshal([]byte(jsonString), &data) if err != nil { fmt.Println("错误:", err) return }
// 通过类型断言访问值 name := data["name"].(string) values := data["values"].([]interface{})