在开发网络服务或处理配置文件时,JSON 几乎无处不在。比如你写一个天气查询的小程序,API 返回的数据就是 JSON 格式。用 Go 语言处理这类数据既高效又方便,标准库 encoding/json 就能搞定大部分需求。
结构体与 JSON 的对应
Go 中最常见的方式是通过结构体(struct)来映射 JSON 数据。假设收到一段用户信息:
{"name": "张三", "age": 28, "email": "zhangsan@example.com"}
可以定义一个结构体来接收:
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
注意后面的 `json:"xxx"` 是标签(tag),它告诉 Go 字段对应 JSON 中的哪个键。没有这个,字段名必须完全匹配,但用了之后就能自由命名。
解析 JSON 字符串
把上面那段 JSON 解析进结构体,用 json.Unmarshal 即可:
jsonData := `{"name": "张三", "age": 28, "email": "zhangsan@example.com"}`
var user User
err := json.Unmarshal([]byte(jsonData), &user)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", user)
输出结果会是:{Name:张三 Age:28 Email:zhangsan@example.com},说明数据已经正确填充。
生成 JSON 字符串
反过来,如果想把结构体转成 JSON 发给前端或保存到文件,用 json.Marshal:
user := User{Name: "李四", Age: 30, Email: "lisi@example.com"}
jsonData, err := json.Marshal(user)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
输出的就是标准格式的 JSON 字符串。默认不带缩进,如果想看清楚点,可以用 json.MarshalIndent:
jsonData, err := json.MarshalIndent(user, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
这样输出会自动换行并用两个空格缩进,调试时更清晰。
处理不确定结构的 JSON
有时候不知道 JSON 长什么样,比如接第三方接口,字段可能随时变。这时候可以用 map[string]interface{} 来接:
var data map[string]interface{}
json.Unmarshal([]byte(jsonData), &data)
fmt.Println(data["name"])
这种方式灵活,但取值时要类型断言,比如 name 实际上是字符串,得这么用:
if name, ok := data["name"].(string); ok {
fmt.Println("用户名:", name)
}
小技巧:忽略空字段
生成 JSON 时,有些字段可能是零值,不想输出。可以在 tag 里加 omitempty:
type Product struct {
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Desc string `json:"desc,omitempty"`
}
如果 Price 是 0,Desc 是空字符串,那它们就不会出现在最终 JSON 中,让数据更干净。
实际项目中,比如做 API 网关、读取配置文件、前后端交互,这些操作每天都会用到。掌握好 Go 处理 JSON 的方法,写代码顺手很多。