如何格式化输出 JSON 中的时间戳

我最近一直在玩围棋,它很棒。在浏览了文档和博客文章之后,我似乎无法理解的是如何让 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 进行编码,但是我不知道这些类型的东西叫什么,所以我甚至不知道用 google 搜索是否也有某种格式选项。

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

作为参考,我已经看过这些页面: 给你给你,当然还有 在官方文件里

101879 次浏览

你可以做的是,包装时间。时间作为你自己的定制类型,并使它实现 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接口。

但是我不知道该怎么做,我只知道我可以在文档类型声明中加入 json: 戳让字段用名称戳而不是戳进行编码,但是我不知道这些类型的东西叫什么,所以我甚至不知道谷歌能找到什么类型的格式选项。

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

您获得的时间字符串表示形式由 Time实现的 MarshalJSON返回。

您可以通过嵌入 time.Time或者包装它,从 Time实现中复制相关的位,从而实现自己的 MarshalJSON方法。包装示例(点击播放) :

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
}

也许另一种方式会让某人感兴趣。我想避免使用别名类型的时间。

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/

我不会使用:

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()}创建的