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

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: ""}

错误原因分析

  1. 未处理JSON字符串的双引号:传入UnmarshalJSON的data是带双引号的JSON字符串(如"2023-08-30T04:03:31.3313066"),直接传入time.Parse会将双引号视为时间的一部分,导致解析失败。
  2. 时间格式不匹配:原格式字符串2006-01-02T15:04:05未包含小数秒部分,无法匹配JSON中带7位小数的时间值。
  3. 字段未导出(潜在问题):结构体字段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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:55:23