在Golang中传出JSON中的格式时间戳?

时间:2014-05-16 12:53:34

标签: json time formatting go

我最近一直在玩Go,这太棒了。我无法弄清楚的事情(在查看文档和博客文章之后)是如何将time.Time类型格式化为我在json.NewEncoder.Encode编码时所需的任何格式

这是一个最小的代码示例:

package main

type Document struct {
    Name        string
    Content     string
    Stamp       time.Time
    Author      string
}

func sendResponse(data interface{}, w http.ResponseWriter, r * http.Request){
     _, err := json.Marshal(data)
    j := json.NewEncoder(w)
    if err == nil {
        encodedErr := j.Encode(data)
        if encodedErr != nil{
            //code snipped
        }
    }else{
       //code snipped
    }
}

func main() {
    http.HandleFunc("/document", control.HandleDocuments)
    http.ListenAndServe("localhost:4000", nil)
}

func HandleDocuments(w http.ResponseWriter,r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    w.Header().Set("Access-Control-Allow-Origin", "*")

    switch r.Method {
        case "GET": 
            //logic snipped
            testDoc := model.Document{"Meeting Notes", "These are some notes", time.Now(), "Bacon"}    
            sendResponse(testDoc, w,r)
            }
        case "POST":
        case "PUT":
        case "DELETE":
        default:
            //snipped
    }
}

理想情况下,我想发送一个请求并将Stamp字段恢复为May 15, 2014而不是2014-05-16T08:28:06.801064-04:00

但我不确定如何,我知道我可以在文档类型声明中添加json:stamp以使用名称戳而不是Stamp来编码字段,但我不知道那些是什么所谓的事物类型,所以我甚至不确定谷歌的内容,以确定是否有某种类型的格式化选项。

有没有人有关于这些类型标记(或者他们被称为)的主题的示例或良好文档页面的链接,或者我如何告诉JSON编码器处理time.Time字段?

仅供参考,我查看了以下网页:herehere,当然还有at the official docs

4 个答案:

答案 0 :(得分:79)

您可以做的是,将time.Time包装为您自己的自定义类型,并使其实现Marshaler接口:

type Marshaler interface {
    MarshalJSON() ([]byte, error)
}

所以你要做的就是:

type JSONTime time.Time

func (t JSONTime)MarshalJSON() ([]byte, error) {
    //do your serializing here
    stamp := fmt.Sprintf("\"%s\"", time.Time(t).Format("Mon Jan _2"))
    return []byte(stamp), nil
}

并制作文件:

type Document struct {
    Name        string
    Content     string
    Stamp       JSONTime
    Author      string
}

并让你的初始化看起来像:

 testDoc := model.Document{"Meeting Notes", "These are some notes", JSONTime(time.Now()), "Bacon"}    

就是这样。如果你想要解组,那么也有Unmarshaler接口。

答案 1 :(得分:36)

也许另一种方式对某人来说很有趣。我想避免在Time中使用别名类型。

type Document struct {
    Name    string
    Content string
    Stamp   time.Time
    Author  string
}

func (d *Document) MarshalJSON() ([]byte, error) {
    type Alias Document
    return json.Marshal(&struct {
        *Alias
        Stamp string `json:"stamp"`
    }{
        Alias: (*Alias)(d),
        Stamp: d.Stamp.Format("Mon Jan _2"),
    })
}

来源:http://choly.ca/post/go-json-marshalling/

答案 2 :(得分:13)

我不会用:

type JSONTime time.Time

我只会将它用于基元(string,int,...)。如果time.Time是一个结构,我需要在每次使用任何time.Time方法时进行转换。

我会这样做(嵌入):

type JSONTime struct {
    time.Time
}

func (t JSONTime)MarshalJSON() ([]byte, error) {
    //do your serializing here
    stamp := fmt.Sprintf("\"%s\"", t.Format("Mon Jan _2"))
    return []byte(stamp), nil
}

无需将t投射到时间。唯一的区别是新实例不是由JSONTime(time.Now())创建的,而是由JSONTime{time.Now()}

创建的

答案 3 :(得分:5)

  

但是我不知道如何,我知道我可以在文档类型声明中添加json:stamp以使用名称戳而非Stamp来编码字段,但我不知道那些类型的东西被称为什么,所以我甚至不确定要谷歌去找出是否有某种类型的格式化选项。

你的意思是tags。但这些不会帮助您解决格式问题。

MarshalJSON实施的Time返回您获得的字符串表示。

您可以通过嵌入MarshalJSON或包装time.Time来复制Time implementation中的相关位,然后继续实施您自己的type ShortDateFormattedTime time.Time func (s ShortDateFormattedTime) MarshalJSON() ([]byte, error) { t := time.Time(s) if y := t.Year(); y < 0 || y >= 10000 { return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]") } return []byte(t.Format(`"Jan 02, 2006"`)), nil } 方法。包装示例(Click to play):

{{1}}