
本文讲解如何通过定义合适的 Go 结构体并合理使用 JSON 标签,将 MongoDB 查询结果序列化为形如 { "array": [ {...}, {...} ] } 的标准 JSON 响应。
本文讲解如何通过定义合适的 go 结构体并合理使用 json 标签,将 mongodb 查询结果序列化为形如 {"array": [{...}, {...}]} 的标准 json 响应。
在 Go 中实现自定义 JSON 输出结构,关键在于结构体字段命名与标签(tag)的精准配合,而非依赖嵌套匿名字段或错误的导出规则。原始代码中存在多个典型问题:student 字段为小写未导出、bson 与 json 标签混用且不一致、嵌套层级与目标 JSON 不匹配。
首先,明确目标 JSON 形态:
{
"array": [
{ "name": "ethan", "Grade": 2 },
{ "name": "rangga", "Grade": 2 }
]
}注意:字段名大小写需与 json tag 严格对应——"name" 小写,"Grade" 首字母大写(Go 中大写即导出),而 "array" 是顶层键名。
✅ 正确做法是定义两个导出结构体(首字母大写),并用 json tag 显式控制序列化键名:
type Student struct {
Name string `json:"name"` // 序列化为小写 "name"
Grade int `json:"Grade"` // 保持首字母大写 "Grade"
}
type StudentsResponse struct {
Array []Student `json:"array"` // 顶层字段名为 "array"
}使用示例(结合 MongoDB 查询场景):
// 假设从 MongoDB 获取了 []studentData 切片
var mongoResults []studentData
err := collection.Find(ctx, bson.M{}).All(ctx, &mongoResults)
if err != nil {
log.Fatal(err)
}
// 转换为可序列化的 Student 切片
students := make([]Student, len(mongoResults))
for i, s := range mongoResults {
students[i] = Student{
Name: s.Name,
Grade: s.Grade,
}
}
// 构建响应结构
response := StudentsResponse{Array: students}
// 序列化输出
jsonData, err := json.MarshalIndent(response, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))⚠️ 注意事项:
- 所有参与 JSON 序列化的字段必须是导出字段(首字母大写),否则 json.Marshal 会忽略它们;
- bson tag 仅用于 MongoDB 驱动反序列化,与 JSON 输出无关,二者应独立设置;
- 若需兼容 MongoDB 存储与 API 响应,可在同一结构体中同时声明 bson 和 json tag,例如:
Name string `bson:"name" json:"name"`
- 避免使用非导出字段(如 student []studentData)作为顶层序列化字段——它永远无法被 json 包访问。
总结:Go 的 JSON 序列化高度依赖结构体可见性与标签声明。要生成嵌套数组 JSON,应设计清晰的导出结构体层级,并通过 json:"key" 精确控制每个字段的输出名称。无需复杂反射或中间转换,标准库即可优雅达成目标格式。


















