echo.context.json() 是 echo 框架内置的 json 响应方法,自动设置 content-type 并调用 json.marshal();需确保字段导出、无循环引用,失败时静默返回 500,建议加错误日志捕获。

echo.Context.JSON() 是最直接的方式
JSON() 是 Echo 框架为 echo.Context 提供的内置方法,专用于序列化结构体或 map 并写入 HTTP 响应体,自动设置 Content-Type: application/json。它底层调用的是 json.Marshal(),所以要求返回值可被 JSON 序列化(字段需导出、无循环引用等)。
- 直接传入状态码和 Go 值即可,例如:
c.JSON(200, map[string]string{"msg": "ok"}) - 如果值是结构体,确保字段以大写字母开头,否则会被忽略(如
Message string✅,message string❌) - 不要手动调用
c.Header("Content-Type", "...")或c.String()再拼 JSON 字符串,否则会覆盖或冲突
遇到空响应或 500 错误,先检查序列化失败
Echo 的 JSON() 在 json.Marshal() 失败时默认返回 500,并静默丢弃错误(不 panic,也不打印日志)。常见原因包括:
- 结构体含不可序列化的字段(如
func、chan、map[interface{}]string) - 时间字段未正确处理:用
time.Time没问题,但若自定义了MarshalJSON()方法且返回错误,就会失败 - 使用了
nil指针字段且没加omitempty标签,而该字段类型本身无法 nil 安全序列化(比如自定义类型未实现MarshalJSON)
建议开发期加一层简单包装来捕获错误:
if err := c.JSON(200, data); err != nil {
c.Logger().Error("JSON marshal failed:", err)
c.JSON(500, map[string]string{"error": "internal error"})
return
}
需要控制时间格式或忽略零值?用结构体 + struct tag
JSON() 本身不提供格式定制,但可通过 Go 结构体的 field tag 控制行为:
- 时间统一转为 ISO8601 字符串:
CreatedAt time.Time <code>json:"created_at"(默认行为) - 自定义时间格式:嵌入
type CustomTime time.Time并实现MarshalJSON() - 忽略空字段:
Name string <code>json:"name,omitempty"(对""、0、nil等零值生效) - 重命名字段:
ID uint <code>json:"id" - 完全排除字段:
Password string <code>json:"-"
注意:omitempty 对指针类型(如 *string)只在指针为 nil 时跳过;对值类型(如 string)则在为空字符串时跳过。
别用 c.String() 或 c.Render() 替代 JSON()
有人试图用 c.String(200, <code>{"msg":"ok"}) 返回 JSON,这会导致两个问题:
- 响应头没设
Content-Type: application/json,前端可能不识别为 JSON - 字符串里的引号、换行、特殊字符容易出错,且无法利用 Go 类型安全做校验
c.Render() 是为模板设计的,需要提前注册模板引擎,对纯 JSON 场景属于过度设计,还可能因模板缓存或路径配置引入意外行为。
真正需要动态生成 JSON 字符串(比如拼接第三方 API 原始响应)时,应显式设置头:c.Header("Content-Type", "application/json"),再用 c.String(),但这种情况极少,优先走 JSON() + 结构体。
实际项目里最容易被忽略的是序列化失败的静默降级——本地测试一切正常,上线后某个边缘数据触发 json.Marshal() 错误,接口就突然返回空白或 500,日志里还没提示。加一行错误日志捕获,能省掉大半排查时间。











