encoding/json – Go语言的JSON编码与解码库
JSON(JavaScript Object Notation)是现代应用中最常用的数据交换格式之一。Go语言标准库中的encoding/json
包提供了完整的JSON编码和解码功能,让我们能够方便地在Go数据结构与JSON格式之间进行转换。
JSON编码(序列化)
将Go数据结构转换为JSON字符串的过程称为编码或序列化。json.Marshal()
函数是实现这一功能的核心方法。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Addr string `json:"addr,omitempty"`
}
func main() {
p := Person{Name: "Alice", Age: 25}
jsonData, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData)) // 输出: {"name":"Alice","age":25}
}
结构体标签
结构体字段可以添加json
标签来控制编码行为:
json:"fieldName"
– 指定JSON字段名称omitempty
– 如果字段为零值,则省略该字段-"
– 完全忽略该字段
JSON解码(反序列化)
将JSON字符串转换回Go数据结构的过程称为解码或反序列化。json.Unmarshal()
函数用于实现这一功能。
jsonStr := `{"name":"Bob","age":30}`
var p Person
err := json.Unmarshal([]byte(jsonStr), &p)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", p) // 输出: {Name:Bob Age:30 Addr:}
处理复杂JSON
嵌套结构体
type Address struct {
City string `json:"city"`
Country string `json:"country"`
}
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Address Address `json:"address"`
}
动态JSON字段(interface{})
当JSON结构不确定时,可以使用interface{}
:
var data map[string]interface{}
jsonStr := `{"name":"Charlie","age":40,"skills":["Go","Python"]}`
err := json.Unmarshal([]byte(jsonStr), &data)
if err != nil {
log.Fatal(err)
}
fmt.Println(data["skills"].([]interface{})[0]) // 输出: Go
流式处理
对于大型JSON数据,可以使用json.Decoder
和json.Encoder
进行流式处理:
// 从标准输入读取并解码JSON
var p Person
decoder := json.NewDecoder(os.Stdin)
err := decoder.Decode(&p)
// 编码并写入标准输出
encoder := json.NewEncoder(os.Stdout)
encoder.Encode(p)
自定义编解码
通过实现json.Marshaler
和json.Unmarshaler
接口,可以自定义类型的编解码行为:
type CustomTime struct {
time.Time
}
func (ct *CustomTime) MarshalJSON() ([]byte, error) {
return []byte(`"` + ct.Format("2006-01-02") + `"`), nil
}
func (ct *CustomTime) UnmarshalJSON(b []byte) error {
s := strings.Trim(string(b), `"`)
t, err := time.Parse("2006-01-02", s)
if err != nil {
return err
}
ct.Time = t
return nil
}
性能优化
- 预分配缓冲区:对于大型JSON,使用
bytes.Buffer
预分配内存 - 重用解码器:避免频繁创建
json.Decoder
实例 - 使用
json.RawMessage
延迟解析部分JSON
常见陷阱
- 未导出字段(小写开头)默认不会被编码
- 循环引用会导致编码失败
- 数字解码为
float64
类型 - JSON中的
null
被解码为Go的nil
总结
encoding/json
包提供了强大而灵活的JSON处理能力,是Go语言中处理JSON数据的首选方案。通过结构体标签、自定义编解码和流式处理等高级特性,我们可以高效地处理各种JSON数据场景。
下一期我们将深入探讨net/http
包 – Go语言强大的HTTP服务器和客户端实现,包括HTTP服务器搭建、路由处理、中间件机制等核心功能。