JSON反序列化日期解析失败,自定义UnmarshalJSON无效求助
JSON时间字段反序列化失败的解决方法
问题背景
尝试反序列化包含timestamp字段的JSON数据时出现解析错误,自定义UnmarshalJSON方法后仍未解决。
相关JSON数据
{ "timestamp": "2023-08-30T04:03:31.3313066" }
自定义时间结构体代码(原错误版本)
type eventTime struct { timeStamp time.Time } func (m *eventTime) UnmarshalJSON(data []byte) error { // Ignore null, like in the main JSON package. if string(data) == "null" || string(data) == `""` { return nil } // Fractional seconds are handled implicitly by Parse. tt, err := time.Parse("2006-01-02T15:04:05", string(data)) *m = eventTime{tt} return err }
报错信息
error(*time.ParseError) *{Layout: "2006-01-02T15:04:05", Value: "\"2023-08-30T04:03:31.3313066\"", LayoutElem: "2006", ValueElem: "\"2023-08-30T04:03:31.3313066\"", Message: ""}
错误原因分析
- 未处理JSON字符串的双引号:传入
UnmarshalJSON的data是带双引号的JSON字符串(如"2023-08-30T04:03:31.3313066"),直接传入time.Parse会将双引号视为时间的一部分,导致解析失败。 - 时间格式不匹配:原格式字符串
2006-01-02T15:04:05未包含小数秒部分,无法匹配JSON中带7位小数的时间值。 - 字段未导出(潜在问题):结构体字段
timeStamp首字母小写,若后续将eventTime作为其他结构体的字段使用,会因字段不可导出导致JSON解析无法赋值。
修正后的代码
import ( "strings" "time" ) type EventTime struct { TimeStamp time.Time // 首字母大写导出字段,兼容外部JSON解析 } func (m *EventTime) UnmarshalJSON(data []byte) error { str := string(data) // 处理null和空字符串场景 if str == "null" || str == `""` { return nil } // 去除JSON字符串的前后双引号 trimmed := strings.Trim(str, `"`) // 优先用匹配7位小数的格式解析,兼容目标JSON的时间格式 tt, err := time.Parse("2006-01-02T15:04:05.0000000", trimmed) if err != nil { // fallback到通用的RFC3339Nano格式,支持最多9位小数秒 tt, err = time.Parse(time.RFC3339Nano, trimmed) if err != nil { return err } } *m = EventTime{TimeStamp: tt} return nil }
验证示例
使用修正后的结构体完成反序列化:
import "encoding/json" func main() { jsonStr := `{"timestamp": "2023-08-30T04:03:31.3313066"}` var result struct { Timestamp EventTime `json:"timestamp"` } err := json.Unmarshal([]byte(jsonStr), &result) if err != nil { panic(err) } println(result.Timestamp.TimeStamp.String()) }
运行后会输出正确解析的时间字符串,无报错。
内容的提问来源于stack exchange,提问作者Ming
相关产品推荐
相关产品推荐

