You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:43:30