本文详解Go标准库json.Marshal在哪些合法输入下会返回非nil错误(而非panic),包括不支持的类型(如channel)和不支持的值(如NaN、无穷大),并提供可运行示例代码。
本文详解go标准库`json.marshal`在哪些合法输入下会返回非nil错误(而非panic),包括不支持的类型(如channel)和不支持的值(如nan、无穷大),并提供可运行示例代码。
在Go中,json.Marshal虽常被视作“安全序列化”工具,但它并非对所有输入都静默处理——当遇到JSON规范无法表达的Go类型或值时,它会明确返回错误,而非触发panic。理解这些边界情况对构建健壮的API序列化逻辑至关重要。
两类明确的错误类型
json.Marshal仅返回两种具体错误类型,均定义在encoding/json包中:
- *json.UnsupportedTypeError:输入为Go中无对应JSON表示的类型(如函数、channel、复杂指针、未导出字段的结构体等);
- *json.UnsupportedValueError:输入类型合法(如float64),但其值本身无法被JSON编码(如NaN、+Inf、-Inf)。
✅ 注意:循环引用(cyclic data)不会返回错误,而是直接引发runtime panic(如fatal error: stack overflow),因此不属于本问题讨论的“返回error”范畴。
示例代码:复现两类错误
以下完整可运行程序清晰展示了两种典型错误场景:
package main
import (
"fmt"
"encoding/json"
"math"
)
func main() {
// 场景1:不支持的类型 —— channel
ch := make(chan int)
_, err1 := json.Marshal(ch)
if err1 != nil {
fmt.Printf("Unsupported type error: %v\n", err1)
// 输出类似:json: unsupported type: chan int
if _, ok := err1.(*json.UnsupportedTypeError); ok {
fmt.Println("→ 类型为 *json.UnsupportedTypeError")
}
}
// 场景2:不支持的值 —— 正无穷大
inf := math.Inf(1)
_, err2 := json.Marshal(inf)
if err2 != nil {
fmt.Printf("Unsupported value error: %v\n", err2)
// 输出类似:json: unsupported value: +Inf
if _, ok := err2.(*json.UnsupportedValueError); ok {
fmt.Println("→ 类型为 *json.UnsupportedValueError")
}
}
// 补充:NaN 和 负无穷同样触发 UnsupportedValueError
nan := math.NaN()
_, err3 := json.Marshal(nan)
fmt.Printf("NaN marshaling error: %v\n", err3) // json: unsupported value: NaN
}
其他常见触发错误的输入
除上述典型外,以下输入也会导致json.Marshal返回错误:
-
未导出(小写首字母)字段的结构体(若无自定义MarshalJSON方法):
type T struct { unexported int } // Marshal(T{}) → error: json: cannot encode unexported field -
包含不支持类型的嵌套结构体/切片/映射:
data := map[string]interface{}{"ch": make(chan bool)} json.Marshal(data) // → UnsupportedTypeError - nil指针指向不支持类型(如*chan int)同样报错,而非忽略。
最佳实践建议
- ✅ 始终检查json.Marshal的返回错误,尤其在处理动态数据(interface{})、用户输入或第三方结构体时;
- ❌ 不要依赖recover()捕获json.Marshal的panic——它只在循环引用时发生,而多数错误是提前返回的;
- ? 对浮点数字段,可在序列化前校验:math.IsNaN(x) || math.IsInf(x, 0);
- ?️ 对敏感结构体,推荐显式实现MarshalJSON()方法,统一控制序列化行为与错误语义。
掌握这些边界条件,能让你的Go JSON序列化逻辑更可靠、可观测,也更符合云原生服务对错误处理的严谨要求。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











