Go语言encoding/json包仅能序列化首字母大写的导出字段;小写字段(如name、things)虽可正常赋值和打印,但会被JSON编码器完全忽略,导致json.Marshal返回空对象{},反序列化后也得到零值。
go语言`encoding/json`包仅能序列化首字母大写的导出字段;小写字段(如`name`、`things`)虽可正常赋值和打印,但会被json编码器完全忽略,导致`json.marshal`返回空对象`{}`,反序列化后也得到零值。
在Go中,JSON序列化与反序列化严格遵循语言的导出规则(Export Rule):只有首字母大写的字段才被视为“导出字段”,才能被encoding/json等外部包通过反射机制访问。而小写字母开头的字段(如name、things)属于包级私有字段,即使已正确初始化、fmt.Println能清晰打印其值,json.Marshal和json.Unmarshal仍会静默跳过——既不报错,也不写入/读取,最终输出{}或解码为零值(如空字符串""、空切片[]string(nil))。
你提供的代码中,问题根源非常典型:
type Message struct {
name string // ❌ 未导出 → JSON包不可见
things []string // ❌ 未导出 → 同样被忽略
}
尽管i := Message{"Steel", []string{"Iron", "Carbon"}}在内存中完全有效,fmt.Println(i)输出{Steel [Iron Carbon]}看似正常,但json.Marshal(i)实际只看到一个“空壳”结构体,故返回字节[123 125](即{}的ASCII编码),反序列化后o自然为{ []}。
✅ 正确做法是:将字段名首字母大写以导出,并配合json标签控制JSON键名,确保API兼容性与可维护性:
type Message struct {
Name string `json:"name"` // ✅ 导出 + 显式映射小写键
Things []string `json:"things"` // ✅ 同上
}
完整可运行示例(含错误处理):
package main
import (
"encoding/json"
"fmt"
"log"
)
type Message struct {
Name string `json:"name"`
Things []string `json:"things"`
}
func main() {
i := Message{
Name: "Steel",
Things: []string{"Iron", "Carbon"},
}
fmt.Printf("Go value: %+v\n", i)
// 输出: Go value: {Name:"Steel" Things:["Iron" "Carbon"]}
b, err := json.Marshal(i)
if err != nil {
log.Fatalf("JSON marshaling failed: %v", err)
}
fmt.Printf("JSON bytes: %v\n", b)
fmt.Printf("JSON string: %s\n", string(b))
// 输出: {"name":"Steel","things":["Iron","Carbon"]}
var o Message
if err := json.Unmarshal(b, &o); err != nil {
log.Fatalf("JSON unmarshaling failed: %v", err)
}
fmt.Printf("Decoded: %+v\n", o)
// 输出: Decoded: {Name:"Steel" Things:["Iron" "Carbon"]}
}
⚠️ 关键注意事项:
- 导出性优先于标签:json:"name"标签仅控制键名,无法绕过导出限制;字段必须大写,否则标签无效。
- 类型一致性同样重要:若JSON中things可能为null或嵌套对象,需考虑使用指针(*[]string)或自定义UnmarshalJSON方法,但基础场景下[]string已足够。
- 推荐始终显式声明json标签:避免Go字段名(如Things)直接作为JSON键("Things"),违背RESTful API小写蛇形命名惯例("things"),也提升前后端契约清晰度。
- HTTP响应中务必检查错误:生产环境切勿忽略json.NewEncoder(w).Encode()的返回错误,否则空响应可能悄无声息地破坏客户端逻辑。
遵循导出规则,是Go中JSON编解码稳定可靠的第一道基石。记住这个口诀:“小写私有,大写导出;标签定名,缺一不可”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











