
json.Marshal在遇到不支持的类型(如channel、func)或非法值(如NaN、无穷大)时会返回具体错误,而非panic;本文通过可运行示例清晰展示两类典型错误输入及其判断方式。
`json.marshal`在遇到不支持的类型(如channel、func)或非法值(如nan、无穷大)时会返回具体错误,而非panic;本文通过可运行示例清晰展示两类典型错误输入及其判断方式。
在 Go 语言中,json.Marshal 虽然常被当作“安全”序列化工具使用,但它并非对所有输入都静默处理——当传入 JSON 规范无法表达的 Go 类型或值时,它会明确返回错误(error),而非触发 panic。理解这些边界情况对构建健壮的 API 序列化逻辑至关重要。
json.Marshal 可能返回两类具体错误:
- *json.UnsupportedTypeError:当尝试序列化不支持的 Go 类型(如 chan、func、unsafe.Pointer、未导出字段的结构体嵌套等);
- *json.UnsupportedValueError:当传入语义上非法的值(如 math.NaN()、math.Inf(1) 或 math.Inf(-1)),这些值在 JSON 中无对应表示(JSON 标准仅支持有限浮点数)。
以下为可直接运行的完整示例,验证两类错误:
package main
import (
"fmt"
"encoding/json"
"math"
)
func main() {
// 示例 1:UnsupportedTypeError —— channel 类型
_, err1 := json.Marshal(make(chan int))
if err1 != nil {
if _, ok := err1.(*json.UnsupportedTypeError); ok {
fmt.Printf("✅ 正确捕获 UnsupportedTypeError: %v\n", err1)
}
}
// 示例 2:UnsupportedValueError —— 正无穷大
_, err2 := json.Marshal(math.Inf(1))
if err2 != nil {
if _, ok := err2.(*json.UnsupportedValueError); ok {
fmt.Printf("✅ 正确捕获 UnsupportedValueError: %v\n", err2)
}
}
// 补充:NaN 同样触发 UnsupportedValueError
_, err3 := json.Marshal(math.NaN())
fmt.Printf("NaN → error? %v\n", err3 != nil) // true
}
⚠️ 注意事项:
- 循环引用(cyclic reference)不会返回错误,而是直接 panic(如 a := &struct{ Next *struct{}{}; }; a.Next = a),因此需在调用前主动检测,不可依赖 error 处理;
- nil 指针、nil slice/map、nil interface 值均合法,分别序列化为 null;
- 匿名函数、方法值、未导出字段(首字母小写)会被忽略,不报错;
- 自定义类型若实现 json.Marshaler 接口,其内部逻辑可能返回其他错误,但那是用户代码责任,不属于 json 包原生错误范畴。
总结:json.Marshal 的错误返回是类型安全与数据合法性校验的第一道防线。开发中应始终检查返回的 error,并根据具体错误类型做差异化处理(如记录日志、拒绝请求或降级响应),而非假设“只要不 panic 就一定成功”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











