golang json反序列化time格式问题

前段时间碰到两处json.Unmarshal()时时间格式错误问题,一处是反序列化php提交的post参数,另一处是从kafka读取的python提交的message。都碰到时间格式不是rfc3339无法解析的问题。查了golang标准库 struct time 源码,发现time默认是以rfc3339的格式进行序列化反序列化的:

// MarshalJSON implements the json.Marshaler interface.
// The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
func (t Time) MarshalJSON() ([]byte, error) {
    if y := t.Year(); y < 0 || y >= 10000 {
        // RFC 3339 is clear that years are 4 digits exactly.
        // See golang.org/issue/4556#c15 for more discussion.
        return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
    }

    b := make([]byte, 0, len(RFC3339Nano)+2)
    b = append(b, '"')
    b = t.AppendFormat(b, RFC3339Nano)
    b = append(b, '"')
    return b, nil
}

// UnmarshalJSON implements the json.Unmarshaler interface.
// The time is expected to be a quoted string in RFC 3339 format.
func (t *Time) UnmarshalJSON(data []byte) error {
    // Ignore null, like in the main JSON package.
    if string(data) == "null" {
        return nil
    }
    // Fractional seconds are handled implicitly by Parse.
    var err error
    *t, err = Parse(`"`+RFC3339+`"`, string(data))
    return err
}

有一个方法是自定义一个time类型,重写MarshalJSON、UnmarshalJSON方法,不过这样当时还需要动到其他地方的代码,所以就没有这样修改。

所以还是希望php和python处传过来的就是rfc3339格式的时间字符串

查了下rfc3339是一个标准的时间格式,每个语言都支持,对应到python语言中,就是datetime的iosformat格式:

In [1]: from datetime import datetime, timezone

In [2]: now = datetime.utcnow()

In [3]: print(now.isoformat())
2019-04-27T09:08:29.837820

以上做法生成的2019-04-27T09:08:29.837820 golang还是无法解析,查了原因是没有带时区信息,加上时区就好了。

In [5]: now = now.replace(tzinfo=timezone.utc)

In [6]: print(now.isoformat())
2019-04-27T09:08:29.837820+00:00

PHP中date也是可以取isoformat格式,就不举例了,还未掌握世界上最好的语言。。。。

所以个人觉得在传日期的时候尽量穿标准的rfc3339时间格式,避免使用自定义的时间格式(如2019-01-12 11:11:11),会省去很多麻烦并避免很多问题。

你可能感兴趣的:(golang json反序列化time格式问题)