【问题标题】:Multiple custom time formats in go for JSON Marshall用于 JSON Marshal 的多种自定义时间格式
【发布时间】:2021-07-20 03:01:21
【问题描述】:

我有一个实用程序函数,用于在 go 中编组和解组自定义时间格式,该函数适用于一种格式字符串,并在 JSON 模型中使用如下

    type Entry struct {
        ID                int              `json:"id"`
        AuthorisedBy      string           `json:"authorisedBy"`
        Duid              string           `json:"duid"`
        IntervalCount     int32            `json:"intervalCount"`
        Intervals         []int32          `json:"intervals"`
        RequestId         string           `json:"requestId"`
        RequestTimestamp  time.Time        `json:"requestTimestamp"`
        TradingDate       utils.CustomTime `json:"tradingDate"`
        Unit              string           `json:"unit"`
        RebidExplanation  string           `json:"rebidexplanation"`
        AcceptedTimestamp time.Time        `json:"acceptedTimestamp"`
}

效用函数。

package utils

import (
    "database/sql/driver"
    "fmt"
    "strings"
    "time"
)

type CustomTime struct {
    time.Time,
}

const ctLayout = "2006-01-02"

func (ct *CustomTime) UnmarshalJSON(b []byte) (err error) {
    s := strings.Trim(string(b), "\"")
    if s == "null" {
        ct.Time = time.Time{}
        return
    }
    ct.Time, err = time.Parse(ctLayout, s)
    return
}

func (ct *CustomTime) MarshalJSON() ([]byte, error) {
    if ct.Time.UnixNano() == nilTime {
        return []byte("null"), nil
    }
    return []byte(fmt.Sprintf("\"%s\"", ct.Time.Format(ctLayout))), nil
}

var nilTime = (time.Time{}).UnixNano()

func (ct *CustomTime) IsSet() bool {
    return ct.UnixNano() != nilTime
}

func (c CustomTime) Value() (driver.Value, error) {
    return driver.Value(c.Time), nil
}

func (c *CustomTime) Scan(src interface{}) error {
    switch t := src.(type) {
    case time.Time:
        c.Time = t
        return nil
    default:
        return fmt.Errorf("column type not supported")
    }
}

我的问题是,我现在需要使用正好 3ms 的字段来格式化其他字段之一,例如 ctLayout = "2006-01-02 15:04:05.000"。

我的问题是,如何设置它,这样我就不需要复制整个结构,有没有办法可以在 Entry 结构中传递 ctLayout 字符串并在实用程序函数中获取它。我确定有,但我这辈子都不知道怎么做。

如果我需要创建一个 CustomTimeMS 类,那就这样吧,但它似乎有很多重复的代码。

谢谢。

【问题讨论】:

  • 谢谢@mkopriva,您能否将您的 cmets 转换为答案...我使用新格式创建了一个新类型,创建了一个 MarshalJSON,它似乎正在工作。似乎它可能有点像一个具有许多不同领域的鼹鼠,但无论如何都适用于这个应用程序。

标签: go time marshalling


【解决方案1】:

两种方式:

一个

将导出的字段 CTLayout 添加到结构 Entry

type Entry struct {
        ID                int              `json:"id"`
        AuthorisedBy      string           `json:"authorisedBy"`
        ...
        ...
        AcceptedTimestamp time.Time        `json:"acceptedTimestamp"`
        CTLayout          string           `json:"-"`
}

更新 MarshalJSON 函数

func (ct *CustomTime) MarshalJSON() ([]byte, error) {
    if ct.Time.UnixNano() == nilTime {
        return []byte("null"), nil
    }
    return []byte(fmt.Sprintf("\"%s\"", ct.Time.Format(ct.CTLayout))), nil
}

由于 CTLayout 已导出,因此可以从任何地方访问。

在对 CustomTime 值调用 json.Marshal 之前使用您需要的内容更新 CTLayout

======================================

两个

添加一个未导出的字段

type Entry struct {
        ID                int              `json:"id"`
        AuthorisedBy      string           `json:"authorisedBy"`
        ...
        ...
        AcceptedTimestamp time.Time        `json:"acceptedTimestamp"`
        ctLayout          string
}

更新 MarshalJSON 函数

func (ct *CustomTime) MarshalJSON() ([]byte, error) {
    if ct.Time.UnixNano() == nilTime {
        return []byte("null"), nil
    }
    return []byte(fmt.Sprintf("\"%s\"", ct.Time.Format(ct.ctLayout))), nil
}

创建一个导出的辅助封送函数

func (ct *CustomTime) Marshal(ctLayout string) ([]byte, error) {
        // You can do whatever else you want here
        // we'll do the obvious
        ct.ctLayout = ctLayout
        return ct.MarshalJSON()
}

致电ct.Marshal(your layout)

如果您有权访问 CustomTime 所在的包,请直接修改 CustomTime 实例,并根据需要取消导出 Marshal

【讨论】:

    【解决方案2】:

    没有一种自动方式将信息从Entry 传递到CustomTimeMarshalJSON 方法,甚至不使用结构标记。我相信,除了创建新类型之外,您唯一能做的就是向CustomTime 添加一个新字段,然后在编组Entry 实例之前,手动将其设置为一些值将指示MarshalJSON 应如何格式化输出。我的建议是创建一个新类型,有点重复但更简洁。

    请注意,嵌入允许您避免重新实现那些应该在嵌入类型和嵌入类型中表现相同的方法。因此,在您的情况下,您只需要重新实现 json 编组和解组方法。不必重新实现 isset、value 和 scan 方法。

    【讨论】:

      猜你喜欢
      • 2012-05-04
      • 1970-01-01
      • 2020-01-23
      • 1970-01-01
      • 2013-11-09
      • 2014-10-22
      • 2020-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多