c.json() 返回空对象或500错误主因是go字段未导出(首字母小写)或含不可序列化类型;需首字母大写字段、避免嵌入context/http.responsewriter;状态码须先c.status()再c.json();中文乱码因默认html转义,应配置jsonencoder为json.marshal。

为什么 c.JSON() 返回空对象或 500 错误
多数人第一次用 c.JSON() 时遇到的不是格式问题,而是 Go 的导出规则限制:只有首字母大写的字段才会被 JSON 序列化。如果结构体字段是 name string(小写),返回就是 {};若结构体里有未导出字段且含指针/接口等无法序列化的值(比如 http.ResponseWriter),c.JSON() 会 panic 并返回 500。
实操建议:
- 结构体字段必须首字母大写,例如
Name string、Email string - 避免在响应结构体中嵌入
context.Context、http.ResponseWriter等非 JSON 友好类型 - 用
json.Marshal()手动测试结构体是否可序列化:data, _ := json.Marshal(yourStruct) fmt.Println(string(data))
如何控制 c.JSON() 的 HTTP 状态码
c.JSON() 默认返回 200,但实际业务中常需返回 201(创建成功)、400(参数错误)、404(未找到)等。Fiber 不提供状态码参数,必须先调用 c.Status() 再调用 c.JSON() —— 顺序不能反,否则状态码会被忽略。
常见用法:
- 创建资源后返回 201:
c.Status(201).JSON(map[string]string{"id": "123"}) - 参数校验失败返回 400:
if !isValid { return c.Status(400).JSON(fiber.Map{"error": "invalid email"}) } - 注意:不能写成
c.JSON(400, ...)——c.JSON()没有状态码参数,这是常见误写
返回自定义结构体 vs fiber.Map 怎么选
fiber.Map 是 map[string]interface{} 的别名,写起来快,适合简单、临时响应;但缺乏类型安全、IDE 提示弱、字段拼错只能运行时发现。自定义结构体则明确、可复用、支持 JSON 标签控制(如 omitempty、json:"user_id")。
推荐策略:
- API 响应结构固定且可能复用(如
UserResponse、ErrorResponse),一定定义结构体 - 调试或原型阶段快速返回几个字段,可用
fiber.Map,但上线前建议替换 - 需要字段条件省略时,结构体 +
omitempty更可靠:type UserResponse struct { ID uint `json:"id"` Name string `json:"name"` Email string `json:"email,omitempty"` // email 为空时不输出 }
中文乱码或特殊字符显示为 \uXXXX 怎么办
Fiber 默认启用 JSON 字符串转义(escape HTML chars),导致中文变成 Unicode 转义序列(如 "\u4f60\u597d")。这不是错误,但影响可读性和前端直接使用。
关闭转义只需在应用初始化时配置:
app := fiber.New(fiber.Config{
JSONEncoder: json.Marshal,
JSONDecoder: json.Unmarshal,
})因为标准 json.Marshal 不转义 HTML 字符,而 Fiber 默认用的是 jsoniter.ConfigCompatibleWithStandardLibrary 的变体(含转义)。
注意点:
- 该配置必须在
fiber.New()时传入,运行时无法修改 - 若你用了自定义 JSON 编码器(如
easyjson),需确保其不开启 HTML 转义 - 前端若依赖转义防 XSS,请自行在业务层处理,不要依赖框架默认行为











