
go 的 string 类型无法表示 json 的 null,必须使用 *string 等可空指针类型,并在序列化时将 nil 指针转为 json null。
go 的 string 类型无法表示 json 的 null,必须使用 *string 等可空指针类型,并在序列化时将 nil 指针转为 json null。
在 Go 的 JSON 序列化中,原生值类型(如 string、int、bool)永远无法生成 null —— 它们只能输出默认零值(""、0、false)。若需在 JSON 中显式表达某个数组元素为 null(例如表示“该职位暂未指定”),唯一标准且可靠的方式是使用指向该类型的指针(如 *string),并让对应字段为 nil。json.Marshal 会自动将 nil 指针序列化为 JSON null。
以问题中的职位列表为例,正确做法如下:
type JobTitles struct {
Titles []*string `json:"titles"` // 注意:此处为 []*string,而非 []string
}
func main() {
// 准备字符串值(非 nil)
ceo := "CEO"
cfo := "CFO"
cmo := "CMO"
// 构造含 nil 的切片:第三项为 nil → JSON 中即为 null
chiefTitles := []*string{&ceo, &cfo, nil, &cmo}
job := JobTitles{Titles: chiefTitles}
data, err := json.Marshal(job)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// 输出: {"titles":["CEO","CFO",null,"CMO"]}
}✅ 关键要点:
- 字段类型必须是 []*string(字符串指针切片),而非 []string;
- 切片中需显式传入 &someString(取地址)或 nil;
- 不可直接写 nil 代替 *string(类型不匹配),也不可对字面量取地址(如 &"CEO" 非法);
- 若需动态构造,可封装辅助函数提升可读性:
func strPtr(s string) *string { return &s }
func nilStr() *string { return nil }
// 使用示例
titles := []*string{
strPtr("CEO"),
strPtr("CFO"),
nilStr(), // 显式表示 null
strPtr("CMO"),
}⚠️ 注意事项:
- 指针带来额外内存分配与 nil 检查开销,高频场景需权衡;
- 反序列化时,nil 对应的字段将保持为 nil 指针,访问前务必判空(if p != nil { use(*p) });
- 若需支持更复杂可空语义(如区分“未设置”和“明确设为空”),可考虑使用 sql.NullString 或自定义类型(需实现 json.Marshaler/Unmarshaler)。
总之,Go 中 JSON 的 null 不是语法糖,而是类型系统的自然体现:只有可空引用类型(指针、接口、切片、map、chan)才能承载 nil,进而被 json 包映射为 null。 掌握这一原则,即可精准控制 JSON 输出结构。


















