web-dev-qa-db-ja.com

Golangの送信JSONでタイムスタンプをフォーマットしますか?

私は最近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
    }
}

理想的には、リクエストを送信し、May 15, 2014ではなく2014-05-16T08:28:06.801064-04:00のようなStampフィールドを取得したいです。

しかし、私は本当にわからない、json:stampをDocument型宣言に追加して、スタンプではなく名前スタンプでエンコードされるフィールドを取得できることを知っているが、それらのタイプのことはわからないと呼ばれるので、その中に何らかの形式のオプションが同様にあるかどうかを調べるために何をグーグルで検索するべきかさえわかりません。

それらのタイプマークアップ(またはそれらが呼び出されるもの)の件名またはtime.Timeフィールドを処理するようJSONエンコーダーに指示する方法について、誰かが例または良いドキュメントページへのリンクを持っていますか?

参考のために、これらのページを見ました: here and here そしてもちろん 公式ドキュメントで

45
EdgeCaseBerg

できることは、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インターフェイスもあります。

83
Not_a_Golfer

おそらく別の方法が誰かにとって興味深いでしょう。 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/

39
s7anley

私は使用しません:

_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()}によって作成されることです

15
user2800844

しかし、私は本当にわからない、json:stampをDocument型宣言に追加して、スタンプではなく名前スタンプでフィールドをエンコードすることができることを知っていますが、それらのタイプの名前がわからない、そのため、その中に何らかの形式のオプションがあるかどうかを調べるために何をグーグルで検索するべきかさえ分かりません。

つまり、 タグ です。しかし、これらはフォーマットの問題には役立ちません。

取得した文字列表現は、 MarshalJSON によって返されます Time によって実装されます。

time.Timeを埋め込むか、または MarshalJSON implementation から関連するビットをコピーすることにより、独自の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
}
5
nemo