Json
在 Go 语言中,处理 JSON 数据非常简单且高效。Go 提供了标准库 encoding/json
,用于编码和解码 JSON 数据。下面是对 Go 中 JSON 处理的详细介绍,包括基本用法、结构体标签、常见操作和常见的陷阱。
1. 基本用法
JSON 编码(序列化)
将 Go 变量转换为 JSON 格式的字符串。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
person := Person{Name: "Alice", Age: 30}
// 将 person 序列化为 JSON 字符串
jsonData, err := json.Marshal(person)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(jsonData)) // 输出: {"Name":"Alice","Age":30}
}
JSON 解码(反序列化)
将 JSON 格式的字符串转换为 Go 变量。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
jsonString := `{"Name":"Alice","Age":30}`
var person Person
// 将 JSON 字符串反序列化为 person
err := json.Unmarshal([]byte(jsonString), &person)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(person) // 输出: {Alice 30}
}
2. 结构体标签
在结构体字段上使用标签可以控制 JSON 编码和解码的行为。例如,可以指定 JSON 字段名、忽略某个字段、指定字段的解码方式等。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"` // JSON 字段名为 "name"
Age int `json:"age"` // JSON 字段名为 "age"
Gender string `json:"gender,omitempty"` // 若为空则忽略该字段
}
func main() {
person := Person{Name: "Alice", Age: 30, Gender: ""}
jsonData, err := json.Marshal(person)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(jsonData)) // 输出: {"name":"Alice","age":30}
}
3. 常见操作
处理嵌套结构体
可以处理包含嵌套结构体的 JSON 数据。
package main
import (
"encoding/json"
"fmt"
)
type Address struct {
City string
Country string
}
type Person struct {
Name string
Age int
Address Address
}
func main() {
jsonString := `{"Name":"Alice","Age":30,"Address":{"City":"New York","Country":"USA"}}`
var person Person
err := json.Unmarshal([]byte(jsonString), &person)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(person) // 输出: {Alice 30 {New York USA}}
}
处理动态 JSON
可以使用 map[string]interface{}
来处理未知结构的 JSON 数据。
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonString := `{"Name":"Alice","Age":30,"Address":{"City":"New York","Country":"USA"}}`
var data map[string]interface{}
err := json.Unmarshal([]byte(jsonString), &data)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(data) // 输出: map[Name:Alice Age:30 Address:map[City:New York Country:USA]]
}
4. 常见陷阱
大小写不匹配
JSON 字段名的大小写敏感,确保结构体标签与 JSON 字段名匹配。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
使用空接口类型
使用 interface{}
可以处理任意类型的数据,但需要进行类型断言。
var data map[string]interface{}
json.Unmarshal([]byte(jsonString), &data)
name := data["Name"].(string)
age := data["Age"].(float64) // JSON 中的数字默认解析为 float64
避免循环引用
Go 的 JSON 编码器不能处理包含循环引用的结构体。
5. 示例代码
下面是一个完整的示例代码,展示了 JSON 编码、解码和处理嵌套结构体:
package main
import (
"encoding/json"
"fmt"
)
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"`
}
func main() {
person := Person{
Name: "Alice",
Age: 30,
Address: Address{
City: "New York",
Country: "USA",
},
}
// JSON 编码
jsonData, err := json.Marshal(person)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(jsonData)) // 输出: {"name":"Alice","age":30,"address":{"city":"New York","country":"USA"}}
// JSON 解码
jsonString := `{"name":"Bob","age":25,"address":{"city":"San Francisco","country":"USA"}}`
var newPerson Person
err = json.Unmarshal([]byte(jsonString), &newPerson)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(newPerson) // 输出: {Bob 25 {San Francisco USA}}
}
总结
Go 语言提供了强大且易用的 encoding/json
包,用于处理 JSON 数据。通过理解 JSON 编码和解码的基本用法、结构体标签的使用、常见操作以及常见陷阱,可以有效地在 Go 程序中处理 JSON 数据。