2013-06-25 16 views
11

Ich habe XML-Daten, die ich über eine REST-API abrufen, die ich in eine GO-Struktur entpacken. Eines der Felder ist ein Datumsfeld, jedoch entspricht das von der API zurückgegebene Datumsformat nicht dem standardmäßigen time.Time-Syntaxformat, und daher schlägt das Unmarshal-Verfahren fehl.Golang XML Unmarshal und time.Time Felder

Gibt es eine Möglichkeit, die unmarshal Funktion anzugeben, welches Datumsformat in der time.Time-Analyse verwendet werden soll? Ich würde gerne richtig definierte Typen verwenden und die Verwendung einer Zeichenfolge, um ein Datetime-Feld zu halten, fühlt sich falsch an.

Beispiel struct:

type Transaction struct { 

    Id int64 `xml:"sequencenumber"` 
    ReferenceNumber string `xml:"ourref"` 
    Description string `xml:"description"` 
    Type string `xml:"type"` 
    CustomerID string `xml:"namecode"` 
    DateEntered time.Time `xml:"enterdate"` //this is the field in question 
    Gross float64 `xml:"gross"` 
    Container TransactionDetailContainer `xml:"subfile"` 
} 

Das Datumsformat zurückgegeben wird "yyyymmdd".

+0

Dies kann helfen, finden, obwohl es sich nur um Rangieren handelt. https://groups.google.com/forum/#!topic/golang-nuts/IM3ZIcYXbz4 – Intermernet

+0

Weitere Informationen finden Sie unter https://code.google.com/p/go/issues/detail?id=2771 – Intermernet

Antwort

40

Ich hatte das gleiche Problem.

time.Time entspricht nicht der xml.Unmarshaler Schnittstelle. Und Sie können kein Datumsformat angeben.

Wenn Sie die Analyse danach nicht behandeln mögen und Sie es vorziehen, die xml.encoding tun, es zu lassen, ist eine Lösung, die eine Struktur mit einem anonymen time.Time Feld zu erstellen und Ihr eigenes UnmarshalXML mit Ihrem benutzerdefinierten Datumsformat implementieren.

type Transaction struct { 
    //... 
    DateEntered  customTime  `xml:"enterdate"` // use your own type that satisfies UnmarshalXML 
    //... 
} 

type customTime struct { 
    time.Time 
} 

func (c *customTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 
    const shortForm = "20060102" // yyyymmdd date format 
    var v string 
    d.DecodeElement(&v, &start) 
    parse, err := time.Parse(shortForm, v) 
    if err != nil { 
     return err 
    } 
    *c = customTime{parse} 
    return nil 
} 

Wenn Ihr XML-Element ein Attribut als Datum verwendet, haben Sie UnmarshalXMLAttr die gleiche Art und Weise umzusetzen.

Siehe http://play.golang.org/p/EFXZNsjE4a

+0

Das hat mich auf den richtigen Weg gebracht. War noch einfacher zu handhaben, wenn ich 'customTime time.Time' stattdessen - keine Notwendigkeit, mit der zugrunde liegenden' time.Time' als Strukturelement zu behandeln. – Colselaw

+1

Beachten Sie, dass DecodeElement einen Fehler zurückgibt, der überprüft und zurückgegeben werden sollte, wenn nicht Null. – AndreiM

1

Von dem, was ich die Codierung/xml gelesen haben hat einige bekannte Probleme, die erst zu einem späteren Zeitpunkt aufschieben wurden ...

Um dieses Problem zu bekommen, anstatt die Art der Verwendung time.Time Verwendung string und behandeln die Parsing danach.

ich ziemlich viel Mühe hatte time.Parse immer in folgendem Format mit Daten zu arbeiten: „Fr, 9. August 2013 19.39.39 GMT“

Seltsamer fand ich, dass „net/http "hat eine ParseTime-Funktion, die eine Zeichenfolge verwendet, die perfekt funktioniert ... http://golang.org/pkg/net/http/#ParseTime

+0

Das Seltsamste, sobald ich den Typ eines Datumsfeldes auf String gesetzt habe, fing alles an zu parsen .... –