json std
在 Go 中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。Go 提供了 encoding/json 标准库,用于处理 JSON 数据,包括序列化(将 Go 数据结构转换为 JSON)和反序列化(将 JSON 转换为 Go 数据结构)。以下是关于 Go JSON 的详细介绍和使用方法:
1. 基础操作:序列化与反序列化
序列化(Struct → JSON)
将 Go 的结构体、切片、Map 等转换为 JSON 格式。
go
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"` // 指定 JSON 字段名
Age int `json:"age"`
Email string `json:"email,omitempty"` // 如果字段为空,则省略
}
func main() {
user := User{Name: "Alice", Age: 25}
jsonData, _ := json.Marshal(user) // 转换为 JSON 字节
fmt.Println(string(jsonData)) // 输出 JSON 字符串
}输出:
json
{"name":"Alice","age":25}反序列化(JSON → Struct)
将 JSON 数据解析为 Go 数据结构。
go
func main() {
jsonData := `{"name":"Alice","age":25}`
var user User
json.Unmarshal([]byte(jsonData), &user) // 解析 JSON
fmt.Println(user.Name) // 输出: Alice
}2. 自定义 JSON 字段
Go 的结构体字段可以通过 json 标签自定义 JSON 字段名或行为:
常用标签说明
json:"字段名":指定字段在 JSON 中的名称。json:"-":忽略字段,不参与序列化或反序列化。json:"字段名,omitempty":如果字段是零值(如空字符串、0、nil),序列化时忽略该字段。
示例:
go
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
Discount bool `json:"-"` // 忽略字段
Stock int `json:"stock,omitempty"` // 零值时忽略
}3. 处理嵌套结构体
JSON 数据可以包含嵌套结构,Go 的结构体支持嵌套解析。
示例:
go
type Address struct {
City string `json:"city"`
State string `json:"state"`
}
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Address Address `json:"address"`
}
func main() {
jsonData := `{
"name": "Alice",
"age": 25,
"address": {
"city": "New York",
"state": "NY"
}
}`
var user User
json.Unmarshal([]byte(jsonData), &user)
fmt.Println(user.Address.City) // 输出: New York
}4. 动态 JSON:使用 map 和 interface{}
对于结构未知或动态的 JSON,可以使用 map 或 interface{} 处理。
解析为 map[string]interface{}
go
func main() {
jsonData := `{"name":"Alice","age":25,"skills":["Go","Python"]}`
var data map[string]interface{}
json.Unmarshal([]byte(jsonData), &data)
fmt.Println(data["name"]) // 输出: Alice
fmt.Println(data["skills"].([]interface{})) // 输出: [Go Python]
}嵌套动态 JSON
go
func main() {
jsonData := `{
"user": {
"name": "Alice",
"age": 25
},
"skills": ["Go", "Python"]
}`
var data map[string]interface{}
json.Unmarshal([]byte(jsonData), &data)
user := data["user"].(map[string]interface{})
fmt.Println(user["name"]) // 输出: Alice
}5. 流式解析 JSON
对于大文件或 JSON 数据流,可以使用 json.Decoder 按流解析,节省内存。
示例:
go
package main
import (
"encoding/json"
"os"
)
func main() {
file, _ := os.Open("data.json")
defer file.Close()
decoder := json.NewDecoder(file)
for {
var record map[string]interface{}
if err := decoder.Decode(&record); err != nil {
break
}
fmt.Println(record)
}
}6. 处理特殊数据类型
时间类型:time.Time
Go 的 JSON 默认不直接支持 time.Time,需要自定义格式。
go
type Event struct {
Name string `json:"name"`
Timestamp time.Time `json:"timestamp"`
}
func main() {
event := Event{Name: "Meeting", Timestamp: time.Now()}
jsonData, _ := json.Marshal(event)
fmt.Println(string(jsonData)) // 输出: {"name":"Meeting","timestamp":"2025-01-01T12:00:00Z"}
// 自定义时间格式
type CustomEvent struct {
Timestamp time.Time `json:"timestamp" format:"2006-01-02"`
}
}7. 错误处理与增强
处理错误
json.Marshal 和 json.Unmarshal 会返回错误,建议始终检查错误:
go
jsonData, err := json.Marshal(data)
if err != nil {
fmt.Println("Error:", err)
}第三方库:go-json
对于高性能场景,可以使用优化版 JSON 库(如 github.com/goccy/go-json),提供更快的序列化与反序列化。
8. JSON 对性能的影响
- JSON 的解析和生成速度较慢,特别是在大数据场景下。
- 如果对性能要求较高,可以考虑使用更高效的数据格式(如 Protobuf、MsgPack)。
总结
- Go 提供了强大的 JSON 支持,适用于大多数场景。
- 通过结构体标签可以自定义 JSON 字段行为。
- 对于动态或复杂 JSON,可以使用
map和interface{}。 - 在大文件或流式数据处理时,推荐使用
json.Decoder。