概述
当使用一个结构体,这个结构体同时需要对应数据库模型以及输出模型的时候,如果时间字段在数据库不为空,我们只能使用sql.NullTime来对应这个时间。但是,这样在输出的时候就会很丑陋(大概是这样的{"Time":"0001-01-01T00:00:00Z","Valid":false}
)
我们希望达到的效果是,如果为空,输出是""
,如果不为空,直接输出时间2006-01...
。如何实现这个效果呢,我们只需要重写一下NullTime即可
重构NullTime
type NullTime struct {
sql.NullTime // 本来我想的是直接用 type NullTime sql.NullTime ,但是这样实现不了。只能通过组合包装实现
}
func (s NullTime) MarshalJSON() ([]byte, error) {// 通过接口实现序列化,注意返回的时候用json.Marshal("") 这里我觉得很离谱,我想直接返回[]byte("")居然不行。
if s.Valid {
res, err := s.Time.MarshalJSON() //如果要想修改时间格式,在这里修改
return res, err
} else {
return json.Marshal("") // 这里很重要
}
}
func (s *NullTime) UnmarshalJSON(b []byte) error { //反序列化
if string(b) == "\"\"" { //这里很离谱,返回的b居然是 "\"\"" 不过仔细想一下也是可以理解的,毕竟json并不知道你这个是数字类型还是字符串类型或其他的,干脆把冒号后面的全给返回给你,自己判断。
return nil
}
err := s.Time.UnmarshalJSON(b)
if err != nil {
return err
}
if !s.Time.IsZero() {
s.Valid = true
}
return nil
}
注意
如果你想实现没有时间的时候是nil,有时间是时间,应该使用 *NullTime.
当然,这里可以使用 time.Time来替换???我不清楚用time.Time会不会在数据库无法写入空字段。需要测试一下