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
相关产品推荐
相关产品推荐

