覆盖json.Marshal使用的布局以格式化time.Time

时间:2013-12-09 16:16:22

标签: json time go marshalling

在Golang中,有没有办法让通用encoding/json Marshal在对time.Time字段进行封送时使用不同的布局?

基本上我有这个结构:

s := {"starttime":time.Now(), "name":"ali"}

我希望使用encdoding/json的{​​{1}}函数对json进行编码,但我想使用我的自定义布局,我想某处调用了Marshal,我想控制那个布局,

3 个答案:

答案 0 :(得分:10)

受到zeebo答案的启发,并在对该答案的评论中加以说明:

http://play.golang.org/p/pUCBUgrjZC

package main

import "fmt"
import "time"
import "encoding/json"

type jsonTime struct {
    time.Time
    f string
}

func (j jsonTime) format() string {
    return j.Time.Format(j.f)
}

func (j jsonTime) MarshalText() ([]byte, error) {
    return []byte(j.format()), nil
}

func (j jsonTime) MarshalJSON() ([]byte, error) {
    return []byte(`"` + j.format() + `"`), nil
}

func main() {
    jt := jsonTime{time.Now(), time.Kitchen}
    if jt.Before(time.Now().AddDate(0, 0, 1)) { // 1
        x := map[string]interface{}{
            "foo": jt,
            "bar": "baz",
        }
        data, err := json.Marshal(x)
        if err != nil {
            panic(err)
        }
        fmt.Printf("%s", data)
    }
}

此解决方案embeds将time.Time放入jsonTime结构中。嵌入促进了jsonTime结构的所有time.Time方法,允许它们在没有显式类型转换的情况下使用(参见// 1)。

嵌入time.Time还有一个缺点,即提升MarshalJSON方法,由于向后兼容性原因,编码/ json封送代码优先于MarshalText方法(MarshalText was added in Go 1.2,MarshalJSON早于此)。因此,使用默认的time.Time格式而不是MarshalText提供的自定义格式。

为了解决这个问题,我们为jsonTime结构覆盖了MarshalJSON。

答案 1 :(得分:6)

这样的事情对你有用吗?

package main

import "fmt"
import "time"
import "encoding/json"

type jsonTime struct {
t time.Time
f string
}

func (j jsonTime) MarshalText() ([]byte, error) {
return []byte(j.t.Format(j.f)), nil
}

func main() {
x := map[string]interface{}{
    "foo": jsonTime{t: time.Now(), f: time.Kitchen},
    "bar": "baz",
}
data, err := json.Marshal(x)
if err != nil {
    panic(err)
}
fmt.Printf("%s", data)
}

也可在此处找到:http://play.golang.org/p/D1kq5KrXQZ

只需按照您希望的方式创建一个实现MarshalText的自定义类型。

答案 2 :(得分:3)

首先,我强烈建议不要使用默认RFC3339以外​​的时间格式。这是一个很好的时间格式,并且可以通过任意数量的语言进行解析,因此除非您需要不同的格式,因为其他人的API需要它,否则最好使用默认格式。

但是,我不得不在消费其他人的API时解决这个问题,所以这里有一个解决方案可以将大部分工作转移到Marshal / Unmarshal步骤,并为您留下理想的结构:{{3} }