2013-12-09 7 views
7

In Golang, gibt es eine Möglichkeit, die generische encoding/json Marshal ein anderes Layout zu verwenden, wenn die time.Time Felder Marshalling?Überschreiben Sie das Layout von json.Marshal zu formatieren time.Time

Im Grunde habe ich diese Struktur:

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

und ich möchte encdoding/json ‚s Marshal Funktion JSon kodieren, aber ich möchte, dass meine benutzerdefinierten Layout verwenden, stelle ich mir irgendwo time.Format(layout) genannt wird, ich will um dieses Layout zu steuern,

Antwort

10

Wie zeebo Antwort inspiriert und gehasht zu dieser Antwort in den Kommentaren aus:

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

Diese Lösung embeds die time.time in die jsonTime Struktur. Die Einbettung fördert die gesamte Zeit. Die Methoden von Time zur jsonTime-Struktur, die ihre Verwendung ohne explizite Typkonvertierung ermöglicht (siehe // 1).

Einbetten einer time.Time hat den Nachteil, auch die MarshalJSON-Methode zu promoten, die aus Gründen der Rückwärtskompatibilität den Code/json marshalling höher priorisiert als die MarshalText-Methode (MarshalText was added in Go 1.2, MarshalJSON geht davor). Daher wird das standardmäßige time.Time-Format anstelle eines von MarshalText bereitgestellten benutzerdefinierten Formats verwendet.

Um dieses Problem zu überwinden, überschreiben wir MarshalJSON für die JSONTIME-Struktur.

+0

Wie würdest du diesen Respekt "omitemperty" auf dem Zeitfeld machen? – nojo

6

Vielleicht funktioniert so etwas für Sie?

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

auch hier zur Verfügung: http://play.golang.org/p/D1kq5KrXQZ

nur einen benutzerdefinierten Typ machen, die MarshalText implementiert, wie Sie es wollen, sich zu zeigen.

+0

Danke, Das ist definitiv ein Schritt nach vorne, aber ich wünschte, ich hätte nicht alle 'time.Time' zu' mytime' und zurück jedes Mal, wenn ich eine Zeit verwenden möchte.Nach oder nach der Zeit.Bevor .. – Ali

+1

Wenn Sie die time.Time-Methoden für den benutzerdefinierten Typ aufrufen möchten, betten Sie eine time.Time ein, anstatt einen Namen zu vergeben. z.B. http://play.golang.org/p/Vudw0hhnwe – ChrisH

+0

Wenn ich mich nicht sehr irre, wenn ich die 'time.Time' einbette, dann funktioniert der' MarshalText' nicht für die JSON-Codierung, was der Grund für alle war Dies zu Beginn. Es muss benannt werden. – Ali

3

Erstens, ich empfehle dringend, ein anderes Zeitformat als die Standard-RFC3339 zu verwenden. Es ist ein gutes Zeitformat und kann von einer beliebigen Anzahl von Sprachen analysiert werden. Wenn Sie also kein anderes Format benötigen, weil die API eines anderen benötigt, ist es wahrscheinlich am besten, den Standard zu verwenden.

Aber ich habe APIs in raubend anderen Leuten dieses Problem zu lösen habe, so ist hier eine Lösung, die den Großteil der Arbeit an dem Marschall/Abstellungs Schritt verschiebt, und läßt Dich mit einer idealen Struktur: http://play.golang.org/p/DKaTbV2Zvl

+0

Wie ist RFC3339 besser als jeder andere? (z. B. RFC822Z) – themihai