在Golang开发中,JSON作为前后端数据交互的通用格式,其处理效率与正确性直接影响接口的稳定性。Golang标准库提供了encoding/json包来完成JSON的序列化与反序列化操作,配合结构体标签可以灵活控制字段的映射规则。

Golang JSON处理基础:序列化与反序列化
encoding/json包提供了Marshal和Unmarshal两个核心函数,分别用于结构体转JSON字符串(序列化)和JSON字符串转结构体(反序列化)。
基础序列化示例
定义一个用户结构体,将其序列化为JSON字符串:
package main
import (
"encoding/json"
"fmt"
)
// 定义用户结构体
type User struct {
Name string `json:"name"` // 字段标签指定JSON中的字段名
Age int `json:"age"`
Email string `json:"email"`
}
func main() {
user := User{
Name: "张三",
Age: 25,
Email: "zhangsan@ipipp.com",
}
// 序列化操作
jsonData, err := json.Marshal(user)
if err != nil {
fmt.Println("序列化失败:", err)
return
}
fmt.Println("序列化结果:", string(jsonData))
}
基础反序列化示例
将JSON字符串反序列化为结构体实例:
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
func main() {
jsonStr := `{"name":"李四","age":28,"email":"lisi@ipipp.com"}`
var user User
// 反序列化操作
err := json.Unmarshal([]byte(jsonStr), &user)
if err != nil {
fmt.Println("反序列化失败:", err)
return
}
fmt.Printf("反序列化结果: 姓名=%s, 年龄=%d, 邮箱=%sn", user.Name, user.Age, user.Email)
}
结构体标签的常用配置技巧
结构体标签可以灵活控制JSON字段的映射、忽略、omitempty等规则,是Golang处理JSON的核心技巧之一。
- 字段名映射:使用
json:"自定义字段名"指定JSON中对应的字段名,解决结构体字段名和JSON字段名不一致的问题。 - 忽略字段:使用
json:"-"可以让该字段不参与序列化与反序列化。 - omitempty规则:使用
json:"字段名,omitempty",当字段为零值(如空字符串、0、nil等)时,序列化时会忽略该字段。 - 类型转换:可以通过标签指定字段的字符串类型,比如
json:"age,string"会将int类型的age序列化为字符串形式的数字。
标签使用示例
package main
import (
"encoding/json"
"fmt"
)
type Product struct {
ID int `json:"id"` // 正常映射
Name string `json:"product_name"` // 映射为product_name
Price float64 `json:"price,omitempty"` // 零值时忽略
Description string `json:"-"` // 忽略该字段
SaleCount int `json:"sale_count,string"` // 序列化为字符串
}
func main() {
product := Product{
ID: 1,
Name: "笔记本电脑",
Price: 0, // 零值,序列化时会被忽略
Description: "高性能游戏本",
SaleCount: 100,
}
data, _ := json.Marshal(product)
fmt.Println(string(data))
}
上述代码输出的JSON结果为:{"id":1,"product_name":"笔记本电脑","sale_count":"100"},可以看到Price和Description字段都被正确处理。
复杂场景的JSON处理技巧
处理嵌套结构体
当JSON结构存在嵌套时,只需要定义对应的嵌套结构体即可,encoding/json会自动处理层级映射:
package main
import (
"encoding/json"
"fmt"
)
type Address struct {
City string `json:"city"`
Street string `json:"street"`
}
type Employee struct {
Name string `json:"name"`
Age int `json:"age"`
Address Address `json:"address"` // 嵌套结构体
}
func main() {
jsonStr := `{"name":"王五","age":30,"address":{"city":"北京","street":"中关村大街"}}`
var emp Employee
json.Unmarshal([]byte(jsonStr), &emp)
fmt.Printf("员工姓名:%s, 城市:%s, 街道:%sn", emp.Name, emp.Address.City, emp.Address.Street)
}
处理动态字段的JSON
如果JSON中存在不确定的字段,可以使用map[string]interface{}来接收,或者使用json.RawMessage延迟解析:
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonStr := `{"name":"赵六","age":32,"extra":{"hobby":"篮球","score":95}}`
// 使用map接收动态字段
var result map[string]interface{}
json.Unmarshal([]byte(jsonStr), &result)
fmt.Println("姓名:", result["name"])
// 解析extra字段
extra := result["extra"].(map[string]interface{})
fmt.Println("爱好:", extra["hobby"])
fmt.Println("分数:", extra["score"])
}
处理JSON数组
JSON数组可以反序列化为切片类型,示例如下:
package main
import (
"encoding/json"
"fmt"
)
type Item struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
jsonArr := `[{"id":1,"name":"商品A"},{"id":2,"name":"商品B"}]`
var items []Item
json.Unmarshal([]byte(jsonArr), &items)
for _, item := range items {
fmt.Printf("ID:%d, 名称:%sn", item.ID, item.Name)
}
}
常见注意事项
- 结构体字段必须是大写开头的可导出字段,否则json包无法访问该字段,会导致序列化反序列化失败。
- 反序列化时,如果JSON中的字段在结构体中不存在,该字段会被自动忽略,不会报错。
- 处理大JSON数据时,可以使用
json.Decoder流式解析,减少内存占用。 - 如果需要自定义序列化逻辑,可以实现
json.Marshaler接口和json.Unmarshaler接口。
GolangJSONencoding_json结构体_tag数据序列化修改时间:2026-06-17 09:51:21