Go语言中如何将JSON反序列化为time.Duration?如何用time.ParseDuration?
在Go中将JSON反序列化为time.Duration的惯用方法
嗨,这个问题问得很实在!Go标准库的encoding/json默认并不支持直接把JSON里的字符串(比如"1h30m")反序列化成time.Duration类型,但我们有一套非常惯用的解决思路,同时我也会把time.ParseDuration的用法给你讲清楚。
一、惯用的JSON反序列化实现方式
核心思路是自定义一个包装类型,实现json.Unmarshaler接口,让JSON解析器知道怎么处理Duration格式的字符串。这样既符合Go的接口设计思想,又能优雅地集成到结构体的反序列化流程中。
完整代码示例
import ( "encoding/json" "fmt" "time" ) // Duration 包装time.Duration,用于实现JSON的反序列化/序列化 type Duration time.Duration // UnmarshalJSON 实现json.Unmarshaler接口,处理JSON字符串到Duration的转换 func (d *Duration) UnmarshalJSON(data []byte) error { // 第一步:先把JSON中的字符串值解析出来(因为传入的data是带双引号的,比如"2h45m") var durationStr string if err := json.Unmarshal(data, &durationStr); err != nil { return fmt.Errorf("duration字段必须是字符串类型,当前输入:%s", data) } // 第二步:用time.ParseDuration解析字符串为time.Duration parsedDur, err := time.ParseDuration(durationStr) if err != nil { return err } // 第三步:把解析结果赋值给自定义的Duration类型 *d = Duration(parsedDur) return nil } // 可选:如果需要把Duration序列化为JSON字符串,实现MarshalJSON接口 func (d Duration) MarshalJSON() ([]byte, error) { return json.Marshal(time.Duration(d).String()) }
如何在结构体中使用
定义包含Duration字段的结构体,直接用自定义类型即可:
type AppConfig struct { RequestTimeout Duration `json:"request_timeout"` CacheTTL Duration `json:"cache_ttl"` } func main() { jsonConfig := `{ "request_timeout": "1m30s", "cache_ttl": "24h" }` var cfg AppConfig if err := json.Unmarshal([]byte(jsonConfig), &cfg); err != nil { panic(err) } // 使用时可以直接转换成time.Duration类型 fmt.Println("请求超时时间:", time.Duration(cfg.RequestTimeout)) fmt.Println("缓存过期时间:", time.Duration(cfg.CacheTTL)) }
二、time.ParseDuration函数的详细用法
time.ParseDuration是Go标准库提供的专门解析持续时间字符串的函数,它支持多种常用的时间单位格式:
- 纳秒:
ns - 微秒:
us或µs - 毫秒:
ms - 秒:
s - 分钟:
m - 小时:
h
基础使用示例
// 解析单个单位 hour, err := time.ParseDuration("1h") if err != nil { panic(err) } fmt.Println(hour) // 输出:1h0m0s // 解析组合单位 halfHour, err := time.ParseDuration("30m15s") fmt.Println(halfHour) // 输出:30m15s // 支持负数持续时间 negativeDur, err := time.ParseDuration("-2h30m") fmt.Println(negativeDur) // 输出:-2h30m0s // 可以直接用于需要Duration的场景,比如休眠 time.Sleep(halfHour)
注意事项
- 函数返回的是
time.Duration类型,本质是一个int64(纳秒数),可以直接进行加减运算。 - 如果解析失败(比如传入了不支持的单位,比如
"1d"代表天,这个函数不支持,需要自己转换),会返回非nil的错误。
补充:非结构体场景的简化处理
如果只是单独解析一个JSON字符串到Duration,不想自定义类型,也可以先把JSON反序列化成字符串,再手动调用time.ParseDuration:
var durStr string json.Unmarshal([]byte(`"1h30m"`), &durStr) dur, _ := time.ParseDuration(durStr) fmt.Println(dur)
但这种方式只适合简单场景,涉及结构体时,自定义类型的方式才是Go社区的惯用做法。
内容的提问来源于stack exchange,提问作者user6216224
相关产品推荐
相关产品推荐

