Golang中json序列化与反序列化
Golang JSON 序列化与反序列化详解
Go语言提供了强大的标准库支持JSON的序列化(编码)和反序列化(解码)。以下是详细的使用方法和示例。
基本概念
- 序列化(编码):将Go的数据结构转换为JSON字符串
- 反序列化(解码):将JSON字符串转换为Go的数据结构
1. 基本的序列化和反序列化
定义结构体
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"` // omitempty表示如果为空则省略
Secret string `json:"-"` // - 表示不序列化该字段
}
序列化示例
package main
import (
"encoding/json"
"fmt"
"log"
)
func main() {
// 创建Person实例
person := Person{
Name: "张三",
Age: 30,
Email: "zhangsan@example.com",
Secret: "不显示的秘密",
}
// 序列化为JSON
jsonData, err := json.Marshal(person)
if err != nil {
log.Fatal("序列化失败:", err)
}
fmt.Println(string(jsonData))
// 输出: {"name":"张三","age":30,"email":"zhangsan@example.com"}
}
格式化序列化
// 使用MarshalIndent生成格式化的JSON
jsonData, err := json.MarshalIndent(person, "", " ")
if err != nil {
log.Fatal("序列化失败:", err)
}
fmt.Println(string(jsonData))
反序列化示例
func main() {
jsonStr := `{"name":"李四","age":25,"email":"lisi@example.com"}`
var person Person
err := json.Unmarshal([]byte(jsonStr), &person)
if err != nil {
log.Fatal("反序列化失败:", err)
}
fmt.Printf("姓名: %s, 年龄: %d, 邮箱: %s\n", person.Name, person.Age, person.Email)
}
2. 处理复杂数据结构
嵌套结构体
type Address struct {
City string `json:"city"`
Country string `json:"country"`
}
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Address Address `json:"address"`
}
func nestedExample() {
user := User{
Name: "王五",
Age: 28,
Address: Address{
City: "北京",
Country: "中国",
},
}
jsonData, _ := json.MarshalIndent(user, "", " ")
fmt.Println(string(jsonData))
}
切片和映射
func sliceMapExample() {
// 切片序列化
names := []string{"Alice", "Bob", "Charlie"}
namesJSON, _ := json.Marshal(names)
fmt.Println("切片:", string(namesJSON))
// 映射序列化
data := map[string]interface{}{
"name": "张三",
"age": 30,
"hobbies": []string{"阅读", "游泳", "编程"},
}
mapJSON, _ := json.MarshalIndent(data, "", " ")
fmt.Println("映射:", string(mapJSON))
// 反序列化到映射
var result map[string]interface{}
json.Unmarshal(mapJSON, &result)
fmt.Println("反序列化结果:", result)
}
3. 自定义序列化和反序列化
实现json.Marshaler接口
type CustomDate struct {
Year int
Month int
Day int
}
// 实现MarshalJSON方法
func (d CustomDate) MarshalJSON() ([]byte, error) {
dateStr := fmt.Sprintf("\"%d-%02d-%02d\"", d.Year, d.Month, d.Day)
return []byte(dateStr), nil
}
// 实现UnmarshalJSON方法
func (d *CustomDate) UnmarshalJSON(data []byte) error {
var dateStr string
if err := json.Unmarshal(data, &dateStr); err != nil {
return err
}
_, err := fmt.Sscanf(dateStr, "%d-%d-%d", &d.Year, &d.Month, &d.Day)
return err
}
type Event struct {
Title string `json:"title"`
Date CustomDate `json:"date"`
}
func customExample() {
event := Event{
Title: "生日派对",
Date: CustomDate{2023, 12, 25},
}
jsonData, _ := json.Marshal(event)
fmt.Println("自定义序列化:", string(jsonData))
// 反序列化
var newEvent Event
json.Unmarshal(jsonData, &newEvent)
fmt.Printf("反序列化: %+v\n", newEvent)
}
4. 处理未知结构的JSON
func unknownStructure() {
jsonStr := `{
"name": "张三",
"age": 30,
"metadata": {
"department": "技术部",
"role": "工程师"
}
}`
var data map[string]interface{}
json.Unmarshal([]byte(jsonStr), &data)
// 类型断言获取值
name := data["name"].(string)
age := data["age"].(float64) // JSON数字默认转为float64
fmt.Printf("姓名: %s, 年龄: %.0f\n", name, age)
// 处理嵌套对象
metadata := data["metadata"].(map[string]interface{})
department := metadata["department"].(string)
fmt.Println("部门:", department)
}
5. 流式处理(处理大文件)
func streamExample() {
// 模拟从文件或网络流读取JSON
jsonStream := `{"name":"用户1","age":25}
{"name":"用户2","age":30}
{"name":"用户3","age":35}`
decoder := json.NewDecoder(strings.NewReader(jsonStream))
for {
var person Person
if err := decoder.Decode(&person); err == io.EOF {
break // 流结束
} else if err != nil {
log.Fatal(err)
}
fmt.Printf("处理用户: %+v\n", person)
}
}
6. 错误处理最佳实践
func safeUnmarshal() {
jsonStr := `{"name":"张三","age":"三十"}` // 错误的age类型
var person Person
if err := json.Unmarshal([]byte(jsonStr), &person); err != nil {
if jsonErr, ok := err.(*json.UnmarshalTypeError); ok {
fmt.Printf("类型错误: 字段 %s 期望类型 %s, 实际值: %s\n",
jsonErr.Field, jsonErr.Type, jsonErr.Value)
} else {
fmt.Printf("JSON解析错误: %v\n", err)
}
return
}
fmt.Printf("成功: %+v\n", person)
}
7. 性能优化技巧
使用json.RawMessage延迟解析
type Message struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"` // 原始JSON数据,延迟解析
}
func rawMessageExample() {
jsonStr := `{
"type": "user",
"data": {"name":"张三","age":30}
}`
var msg Message
json.Unmarshal([]byte(jsonStr), &msg)
switch msg.Type {
case "user":
var user Person
json.Unmarshal(msg.Data, &user)
fmt.Println("用户数据:", user)
case "product":
// 解析为产品数据结构
}
}
总结
Go语言的JSON处理非常强大和灵活,主要特点包括:
- 简单易用:通过结构体tag轻松控制序列化行为
- 类型安全:编译时类型检查
- 高性能:标准库经过高度优化
- 灵活性:支持自定义序列化逻辑
在实际开发中,建议:
- 始终处理错误
- 对于大型数据使用流式处理
- 使用
omitempty避免空值污染JSON输出 - 对于复杂场景考虑实现自定义的Marshaler/Unmarshaler接口

浙公网安备 33010602011771号