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

Go自定义MarshalJSON序列化ISODate时结果不一致问题

Go自定义MarshalJSON部分场景不生效问题解答

问题根因

这属于Go的预期特性,问题出在你的MarshalJSON方法使用了指针接收器,结合Go的方法集规则、map值不可寻址的特性共同导致:

  • Go方法集规则:值类型ISODate的公开方法集仅包含值接收器定义的方法,仅指针类型*ISODate的方法集包含你实现的指针接收器MarshalJSON方法
  • map的value默认不可寻址:序列化map[int]ISODate时,json序列化器无法对map中的ISODate值取地址,因此无法匹配到指针接收器的MarshalJSON方法,最终 fallback 到内嵌的time.Time自带的序列化逻辑,输出了带时区的完整时间格式
  • 切片/数组的元素是可寻址的:序列化[]ISODate时,序列化器可以正常获取切片元素的指针,因此自动匹配到你写的MarshalJSON方法,输出符合预期的日期格式

修复方案

提供两种可行的修复方式,按需选择:

方案1:将MarshalJSON改为值接收器(最通用)

直接修改方法的接收器为值类型,这样不管是值还是指针类型的ISODate都能匹配到该序列化方法:

// 把接收器从 *ISODate 改成 ISODate 即可
func (ct ISODate) MarshalJSON() ([]byte, error) {
    if ct.Time.UnixNano() == nilTime {
        return []byte("null"), nil
    }
    return []byte(fmt.Sprintf("\"%s\"", ct.Time.Format("2006-01-02"))), nil
}

修改后两种场景的输出都会统一为"9999-12-31"格式。

方案2:map存储指针类型的ISODate

如果因业务逻辑需要必须保留指针接收器,把map的value类型改为*ISODate即可:

m1 := map[int]*ISODate{1: &d}

这样序列化时可以直接调用指针接收器的MarshalJSON方法。


内容的提问来源于stack exchange,提问作者abcalphabet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 07:54:01