Golang中传出JSON格式时间戳?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23695479/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:18:59  来源:igfitidea点击:

Format Timestamp in outgoing JSON in Golang?

jsontimeformattinggo

提问by EdgeCaseBerg

I've been playing with Go recently and it's awesome. The thing I can't seem to figure out (after looking through documentation and blog posts) is how to get the time.Timetype to format into whatever format I'd like when it's encoded by json.NewEncoder.Encode

我最近一直在玩围棋,它很棒。我似乎无法弄清楚(在查看文档和博客文章之后)是如何将time.Time类型格式化为我想要的任何格式,当它被编码时json.NewEncoder.Encode

Here's a minimal Code example:

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

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
    }
}

Ideally, I'd like to send a request and get the Stamp field back as something like May 15, 2014and not 2014-05-16T08:28:06.801064-04:00

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

But I'm not really sure how, I know I can add json:stampto the Document type declaration to get the field to be encoded with the name stamp instead of Stamp, but I don't know what those types of things are called, so I'm not even sure what to google for to find out if there is some type of formatting option in that as well.

但我不太确定如何,我知道我可以添加json:stamp到 Document 类型声明中以使用名称戳而不是 Stamp 对字段进行编码,但我不知道这些类型的东西被称为什么,所以我我什至不知道该用什么 google 来找出其中是否也有某种格式的选项。

Does anyone have a link to the an example or good documentation page on the subject of those type mark ups (or whatever they're called) or on how I can tell the JSON encoder to handle time.Timefields?

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

Just for reference, I have looked at these pages: hereand hereand of course, at the official docs

仅供参考,我查看了这些页面:这里这里,当然还有官方文档

回答by Not_a_Golfer

What you can do is, wrap time.Time as your own custom type, and make it implement the Marshalerinterface:

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

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

So what you'd do is something like:

所以你要做的是:

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
}

and make document:

并制作文件:

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

and have your intialization look like:

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

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

And that's about it. If you want unmarshaling, there is the Unmarshalerinterface too.

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

回答by s7anley

Perhaps another way will be interesting for someone. I wanted to avoid using alias type for 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"),
    })
}

Source: http://choly.ca/post/go-json-marshalling/

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

回答by pete911

I would NOT use:

我不会使用:

type JSONTime time.Time

I would use it only for primitives (string, int, ...). In case of time.Timewhich is a struct, I would need to cast it every time I want to use any time.Timemethod.

我只会将它用于原语(字符串,整数,...)。如果time.Time哪个是结构体,则每次我想使用任何time.Time方法时都需要对其进行转换。

I would do this instead (embedding):

我会这样做(嵌入):

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
}

No need to cast tto time. The only difference is that new instance is NOT created by JSONTime(time.Now())but by JSONTime{time.Now()}

没有必要施展t时间。唯一的区别是新实例不是由创建JSONTime(time.Now())而是由JSONTime{time.Now()}

回答by nemo

But I'm not really sure how, I know I can add json:stamp to the Document type declaration to get the field to be encoded with the name stamp instead of Stamp, but I don't know what those types of things are called, so I'm not even sure what to google for to find out if there is some type of formatting option in that as well.

但我不太确定如何,我知道我可以将 json:stamp 添加到 Document 类型声明中,以便使用名称图章而不是 Stamp 对字段进行编码,但我不知道这些类型的东西被称为什么,所以我什至不知道该用什么 google 来找出其中是否也有某种格式的选项。

You mean tags. But these won't help you with your formatting problem.

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

The string representation you get for your time is returned by MarshalJSONimplemented by Time.

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

You can go ahead and implement your own MarshalJSONmethod by copying the relevant bits from the Timeimplementationby either embedding time.Timeor wrapping it. Wrapping example (Click to play):

您可以通过嵌入或包装MarshalJSONTime实现中复制相关位来继续实现自己的方法time.Time。包装示例(点击播放):

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
}