如何使用Golang encoding/json解析JSON_序列化和反序列化结构体

Go语言encoding/json包通过导出字段和json标签实现JSON编解码:导出字段(首字母大写)才能被处理,json:"name"自定义键名,omitempty忽略零值,"-"忽略字段,",string"字符串化编解码;需传指针给Unmarshal并检查错误,Marshal支持格式化输出;嵌套结构、切片、map及map[string]interface{}均自动递归处理。

Go 语言的 encoding/json 包提供了简洁、高效的方式处理 JSON 序列化(struct → JSON)和反序列化(JSON → struct)。关键在于结构体字段的可见性(首字母大写)、标签(json:"field_name")控制映射关系,以及正确处理嵌套、空值和类型兼容性。

结构体定义与 JSON 标签

只有导出字段(首字母大写)才能被 JSON 包读写。使用 json 标签可自定义字段名、忽略字段或控制空值行为:

  • json:"name":指定 JSON 中对应的键名
  • json:"name,omitempty":该字段为空值(零值)时不输出到 JSON
  • json:"-":完全忽略该字段
  • json:",string":将数字/布尔等类型以字符串形式编解码(如 "123"int

示例:

type User struct {
    ID     int    `json:"id"`
    Name   string `json:"name"`
    Email  string `json:"email,omitempty"`
    Active bool   `json:"active,string"` // 接收 "true"/"false" 字符串
    Secret string `json:"-"`
}

反序列化:JSON 字符串 → 结构体

json.Unmarshal 将字节切片([]byte)解析为结构体指针。务必传入指针,否则无效果;并检查错误:

data := []byte(`{"id": 1, "name": "Alice", "active": "true"}`)
var u User
err := json.Unmarshal(data, &u)
if err != nil {
    log.Fatal(err)
}
// u.ID == 1, u.Name == "Alice", u.Active == true

注意:
- JSON 键名不区分大小写,但需与标签完全匹配(除非手动处理)
- 如果 JSON 中有额外字段而结构体没有对应字段,默认忽略
- 类型不匹配(如字符串赋给 int)会返回错误

序列化:结构体 → JSON 字符串

json.Marshal 将结构体转为 []byte。推荐用 json.MarshalIndent 生成格式化 JSON(便于调试):

u := User{ID: 2, Name: "Bob", Active: true}
b, err := json.Marshal(u)
// → {"id":2,"name":"Bob","active":"true"}

b, err := json.MarshalIndent(u, "", " ") // → {
"id": 2,
"name": "Bob",
"active": "true"
}

如果字段是 nil 指针或零值且带 omitempty,不会出现在结果中。

处理嵌套、切片与 map

结构体字段可以是其他结构体、切片或 map,encoding/json 会自动递归处理:

type Post struct {
    Title string   `json:"title"`
    Tags  []string `json:"tags"`
    Author *User   `json:"author,omitempty"`
}

type Blog struct { Posts []Post json:"posts" Meta map[string]interface{} json:"meta" }

反序列化时,只要 JSON 数据结构匹配,就能正确填充。map[string]interface{} 可用于动态或未知结构的字段(需运行时类型断言)。