使用自定义JSON Marshal()进行嵌入式结构的问题

时间:2015-11-13 22:13:25

标签: json struct go

我正在尝试定义自定义JSON编组程序以显示特定格式的某些时间信息。理想情况下,我希望有一个结构来存储创建/修改的值,然后将它们嵌入到需要跟踪该信息的结构中。另外,我想在JSON封送程序中定义一个自定义日期格式,以便从客户端应用程序中使用。

我目前有两个结构

type Timestamp struct {
    Created time.Time
    Modified time.Time
}

type Company struct {
    Id string
    Name string
    Timestamp    
}

我想将Timestamp结构嵌入到需要记录项目更新/创建时的对象中。那里什么都没有。

我定义

时出现问题
func (t Timestamp) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        CreatedFormatted string
    }{
        CreatedFormatted: t.Created.Format("Monday Jan _2 15:04:05 2006"),
    })
}

当我去编组Company时,我只看到时间戳的json,但公司没有。我原以为会显示公司struct 时间戳结构的内容。我在这里做错了吗?

2 个答案:

答案 0 :(得分:3)

当结构中嵌入的类型提供方法时,该方法将成为嵌入结构的一部分。由于Company嵌入TimestampTimestamp MarshalJSON也可用于Company。当json想要编组Company时,它会看到它有一个MarshalJSON方法并调用它 - 它找到的方法只会编组时间戳字段。结构的默认行为(将每个字段封送到JSON对象中的自己的键)被覆盖。

你能做什么:

  1. 不要使用struct embedding,只需将Timestamp设为常规字段(即使您将其声明为Timestamp Timestamp)。然后Company不会继承其方法,JSON将按预期工作(但代码中希望嵌入的其他部分可能会发生变化)。或者:
  2. 授予Company自己的MarshalJSON方法,该方法可以对包括时间戳在内的所有字段进行整理。你可以通过
    做到这一点 一个。将字段复制到与Company相同但没有嵌入的其他类型,并将其编组。
    湾将字段复制到地图中并对其进行编组。
    C。单独编组每个字段并自己粘贴fmt.Sprintf({"key1":%s,"key2":%s,...}, m1, m2, ...)

答案 1 :(得分:0)

通过在Timestamp中嵌入Company,您不仅可以共享成员变量,还可以使用方法。这意味着您提供了Company.MarshalJSON方法,然后由json包用于编组整个结构。为了查看所有字段,您还需要为Company结构实现显式封送程序。

如果您只想以特定方式格式化时间戳,另一种解决方案是提供您自己的time.Time并在那里提供JSON编组。

例如:

type AccessTime time.Time

func (t AccessTime) MarshalJSON() ([]byte, error) {
    return json.Marshal(time.Time(t).Format("Monday Jan _2 15:04:05 2006"))
}

type Timestamp struct {
    Created  AccessTime
    Modified AccessTime
}

https://play.golang.org/p/PhZXPauSyz