2013-12-09 1 views
7

Golangでは、encoding/jsontime.Timeフィールドをマーシャリングするときにマーシャリングが異なるレイアウトを使用する方法がありますか?私が欲しい、私はどこかtime.Format(layout)が呼び出されている想像し、json.Marshalで使用されるレイアウトをオーバーライドしてtime.Timeをフォーマットします

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

と私はencdoding/jsonさんMarshal機能を使用してJSONにエンコードしたいが、私は私のカスタムレイアウトを使用したい:基本的に

私は、この構造体を持っていますそのレイアウトを制御するには、

答えて

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 jsonTime構造体へのtime.Time。埋め込みはすべてのtime.TimeのメソッドをjsonTime構造体に昇格させ、明示的な型変換なしでその使用を可能にします(// 1を参照)。

埋め込むtime.Timeには、MarshalJSONメソッドも宣伝されているという欠点があります。これは、encoding/jsonマーシャリングコードが後方互換性の理由でMarshalTextメソッドよりも優先順位が高くなります(MarshalText was added in Go 1.2、MarshalJSONより前です)。その結果、MarshalTextによって提供されるカスタム形式の代わりに、デフォルトのtime.Time形式が使用されます。

この問題を解決するために、jsonTime構造体のMarshalJSONをオーバーライドします。

+0

あなたはこの敬意を時間フィールドで "omitempty"とどのようにしますか? – nojo

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にあなたがそれを表示したいの方法を実装するカスタムタイプを作ります。

+0

ありがとうございました。確かに一歩前進ですが、私はすべてのtime.Timeを 'mytime'に変換する必要はありませんでしたし、いつでも私は時間を使いたいと思っています.Afterまたはtime.Before .. – Ali

+1

カスタムタイプのtime.Timeメソッドを呼び出す場合は、time.Timeを埋め込みます。例えばhttp://play.golang.org/p/Vudw0hhnwe – ChrisH

+0

私が間違っていない限り、 'time.Time'を埋め込むと、' MarshalText'はjsonエンコーディングのためには機能しません。これはまず始まります。名前を付ける必要があります。 – Ali

3

最初に、デフォルトのRFC3339以外​​の時間形式を使用することを強くお勧めします。それは良い時間フォーマットであり、任意の数の言語で解析できるので、他の誰かのAPIがそれを必要とするため、異なるフォーマットが必要な場合を除き、おそらくデフォルトを使用するのが最善です。 http://play.golang.org/p/DKaTbV2Zvl

はしかし、私はここに元帥/非整列化ステップへの仕事の大部分を移動させる一つの解決策であり、理想的な構造であなたを残し、他の人のAPIを消費するには、この問題を解決するために持っていました

+0

どのようにRFC3339が他のどのタイプより優れていますか? (例えばRFC822Z) – themihai

関連する問題