以下为 Go语言 encoding/json 库的深度解析,涵盖JSON编解码、结构体标签与自定义序列化的核心机制,与标准库(fmt、time等)保持一致的文档风格:
一、核心功能概览
功能分类 | 核心函数/方法 | 作用描述 |
基础编解码 | json.Marshal(v), json.Unmarshal(data, v) | 结构体与JSON互转 |
流式处理 | json.NewEncoder(w io.Writer), json.NewDecoder(r io.Reader) | 高效处理大JSON数据流 |
结构体标签 | ` `json:"key,option"` ` | 控制字段映射规则 |
自定义序列化 | 实现 MarshalJSON() ([]byte, error), UnmarshalJSON([]byte) error | 完全自定义JSON生成/解析逻辑 |
二、基础JSON编解码
1. 序列化(Marshal)
type User struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
user := User{Name: "Alice", Age: 30}
data, err := json.Marshal(user) // {"name":"Alice","age":30}
// 格式化输出
dataIndent, _ := json.MarshalIndent(user, "", " ")
/*
{
"name": "Alice",
"age": 30
}
*/
2. 反序列化(Unmarshal)
jsonStr := `{"name":"Bob","age":25}`
var user User
err := json.Unmarshal([]byte(jsonStr), &user) // user = User{Name:"Bob", Age:25}
三、结构体标签高级用法
1. 标签选项详解
标签格式 | 作用描述 | 示例 |
json:"-" | 忽略字段 | Password string json:"-"`` |
json:"name" | 指定JSON字段名 | Name string json:"user_name"`` |
json:",omitempty" | 零值时忽略字段 | Age int json:",omitempty"`` |
json:",inline" | 嵌套结构体展开(需自定义Unmarshal) | Profile json:",inline"`` |
2. 嵌套与匿名结构体
type Address struct {
City string `json:"city"`
Street string `json:"street"`
}
type User struct {
Name string `json:"name"`
Address `json:"address"` // 嵌套结构体
}
// JSON示例:{"name":"Alice","address":{"city":"Shanghai","street":"Nanjing Rd"}}
四、自定义序列化逻辑
1. 实现 MarshalJSON方法
type CustomTime time.Time
func (ct CustomTime) MarshalJSON() ([]byte, error) {
t := time.Time(ct)
return []byte(fmt.Sprintf(`"%s"`, t.Format("2006-01-02"))), nil
}
// 使用示例
type Event struct {
Time CustomTime `json:"time"`
}
event := Event{Time: CustomTime(time.Now())}
json.Marshal(event) // {"time":"2023-08-25"}
2. 实现 UnmarshalJSON方法
func (ct *CustomTime) UnmarshalJSON(data []byte) error {
str := strings.Trim(string(data), `"`)
t, err := time.Parse("2006-01-02", str)
*ct = CustomTime(t)
return err
}
五、高效处理技巧
1. 流式编码解码
场景 | 方法 | 优点 |
大JSON文件读取 | decoder := json.NewDecoder(file) | 内存占用恒定 |
HTTP响应流处理 | json.NewEncoder(w).Encode(data) | 直接写入网络连接 |
流式解码示例:
file, _ := os.Open("large.json")
decoder := json.NewDecoder(file)
// 读取JSON数组
_, _ = decoder.Token() // 跳过起始的 '['
for decoder.More() {
var item Item
_ = decoder.Decode(&item)
process(item)
}
2. 性能优化策略
- 预分配内存:为切片/映射设置初始容量
type Response struct {
Items []Item `json:"items"`
}
res := Response{Items: make([]Item, 0, 100)} // 预分配100容量
- 使用 json.RawMessage 延迟解析:
type Message struct {
Header map[string]string `json:"header"`
Body json.RawMessage `json:"body"` // 延迟解析
}
六、错误处理与陷阱
1. 常见错误类型
错误场景 | 解决方案 |
未导出字段 | 确保结构体字段首字母大写 |
循环引用 | 使用json:"-"忽略或指针引用 |
数值精度丢失 | 使用string标签或自定义类型 |
时间格式不匹配 | 自定义时间类型或指定time.RFC3339 |
2. 严格模式校验
decoder := json.NewDecoder(reader)
decoder.DisallowUnknownFields() // 禁止未知字段
err := decoder.Decode(&config) // 若JSON含未定义字段,返回错误
七、实战示例
1. 动态JSON解析
var data map[string]interface{}
jsonStr := `{"name":"Alice","age":30,"skills":["Go","Python"]}`
json.Unmarshal([]byte(jsonStr), &data)
// 类型断言获取值
if age, ok := data["age"].(float64); ok { // JSON数字默认解析为float64
fmt.Println(int(age)) // 30
}
2. 配置管理系统
type Config struct {
Port int `json:"port"`
Env string `json:"env"`
Plugins []string `json:"plugins,omitempty"`
}
func LoadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("invalid config: %v", err)
}
return &cfg, nil
}
八、扩展工具与库
工具库 | 优势 | 使用场景 |
jsoniter | 高性能替代实现(兼容标准库) | 高频JSON处理 |
easyjson | 代码生成式高性能序列化 | 对性能要求极高的场景 |
mapstructure | 将map解析到结构体 | 动态JSON结构处理 |
通过系统掌握 encoding/json 库,可高效处理各类JSON数据交互场景。建议结合以下实践:
- 严格校验:生产环境开启 DisallowUnknownFields
- 性能监控:使用 go test -bench 测试序列化性能
- 版本兼容:通过结构体标签处理字段变更(如重命名、弃用字段)