2014-10-31 170 views
2

我想獲得一個HTTP請求體,它是一個json對象並將其解碼爲我定義的Go結構。Json解碼無法解析json中的時間戳成Go結構

結構的兩個字段是time.Time類型。雖然只有一個這種類型的領域,一切工作正常。

如果我在旅​​途結構不止一個time.Time類型的字段我不能解碼,並得到了錯誤:

2014/11/01 01:07:04 parsing time "null" as ""2006-01-02T15:04:05Z07:00"": cannot parse "null" as """

的問題是在解碼線。儘管我進行了調試,但我仍然可以達成有意義的結果。這個問題似乎很奇怪,實際上不應該是這樣。

我在這裏錯過了什麼?

func register(w http.ResponseWriter, r *http.Request){ 
//Read Request Body JSON Into Go Types 

var requestBody = []byte(`{"username":"qwewwwqweqwe","password":"can","usertype":"student","firstname":"",‌​"midname":null,"surname":null,"signuptimestamp":null,"userstatus":null,"phone":nu‌​ll,"email":null,"address":null,"city":null,"country":null,"language":null,"lastlo‌​gintimestamp":null}`) 

type RegisterStructure struct { 
    Id int `json:"id"` 
    Timestamp time.Time `json:"timestamp,omitemty"` 
    SignupTimestamp time.Time `json:"signuptimestamp,omitempty"` 
    Username string `json:"username"` 
    Password string `json:"password"` 
    UserType string `json:"usertype"` 
    FirstName string `json:"firstname"` 
    Midname string `json:"midname"` 
    Surname string `json:"surname"` 
    UserStatus string `json:"userstatus"` 
    Phone string `json:"phone"` 
    Email string `json:"email"` 
    Address string `json:"address"` 
    City string `json:"city"` 
    Country string `json:"country"` 
    Language string `json:"language"` 
    //LastLoginTimestamp time.Time `json:"lastlogintimestamp,omitempty"` 
} 
var registerInstance RegisterStructure 
var now = time.Now() 
fmt.Printf("now is %v", now) 
fmt.Println() 
fmt.Printf("1 registerInstance after inited here is %v", registerInstance) 
fmt.Println() 

registerInstance = RegisterStructure{Timestamp: now, SignupTimestamp: now,} 
fmt.Printf("registerInstance after set to var now here is %v", registerInstance) 
fmt.Println() 

dec := json.NewDecoder(bytes.NewReader(requestBody)) 
err = dec.Decode(&registerInstance) 
if err != nil { 
    fmt.Printf("error happens here.") 
    log.Fatal(err) 
} 
+0

沒有足夠的信息複製或驗證。請修改問題以顯示示例請求主體。如果有幫助,請執行:'fmt.Println(「%#v」,requestBody)',這樣我們就知道正在分析什麼樣的東西,並且可以嘗試重現您的問題。另外,你的問題並沒有令人信服地表明解析是問題:你怎麼知道解析導致了問題?目前,你已經顯示了日誌消息,但是日誌可能沒有顯示正確的東西?程序中的哪一行對應於程序中的哪個日誌記錄?我們不知道。 – dyoo 2014-10-31 23:54:43

+0

我用你的fmt代碼輸出後我的請求正文是這樣的:'%#v [123 34 117 115 101 114 110 97 109 101 34 ........ 17 115 101 114 115 116 97 116 117 115 34 58 110 117 108 108 44 34 8 108 125]' – 2014-10-31 23:58:43

+0

關於測井線;我看不到'fmt.Printf(「錯誤發生在這裏。」)之後的任何日誌行''。所以我猜測編碼是除了與解析有關的錯誤消息的引導之外的問題。 – 2014-10-31 23:59:25

回答

5

好的。這裏是一個reproducible example,顯示你看到的錯誤。

package main 

import (
    "encoding/json" 
    "fmt" 
    "bytes" 
    "time" 
) 

type RegisterStructure struct { 
    SignupTimestamp time.Time `json:"signuptimestamp,omitempty"` 
} 

func main() { 
    requestBody := []byte(`{"signuptimestamp" : null}`) 
    dec := json.NewDecoder(bytes.NewReader(requestBody)) 
    registerInstance := RegisterStructure{} 
    err := dec.Decode(&registerInstance) 
    if err != nil { 
     fmt.Println(err) 
    } 
} 

您看到的錯誤與擁有多個時間戳無關。這就是爲什麼顯示輸入對於調試這種情況至關重要的原因,以及爲什麼你應該回去改變你的問題以包含樣本requestBody作爲問題內容的一部分。否則,它就變成很難很難猜到你在做什麼。

發生了什麼事是null不是由JSON解組器處理的time.Timedocumentation for time.Time's unmarshaller說:UnmarshalJSON實現了json.Unmarshaler接口。預計該時間是RFC 3339格式中的帶引號的字符串。

null不是這樣一個值:在這種情況下,解碼器不會嘗試構造時間戳的「零」值。

你想要做的是改變SignupTimestamptime.Time類型*time.Time,使null值可以明確地表示爲nil指針。

這裏是一個example證明:

package main 

import (
    "bytes" 
    "encoding/json" 
    "fmt" 
    "time" 
) 

type RegisterStructure struct { 
    SignupTimestamp *time.Time `json:"signuptimestamp,omitempty"` 
} 

func main() { 
    requestBodies := []string{ 
     `{"signuptimestamp" : "1985-04-12T23:20:50.52Z"}`, 
     `{"signuptimestamp" : null}`, 
    } 
    for _, requestBody := range requestBodies { 
     dec := json.NewDecoder(bytes.NewReader([]byte(requestBody))) 
     registerInstance := RegisterStructure{} 
     err := dec.Decode(&registerInstance) 
     if err != nil { 
      fmt.Println(err) 
     } 
     fmt.Printf("%#v\n", registerInstance) 
    } 
} 
+0

我已經初始化了time.Time類型的字段'Timestamp'和'SignupTimestamp'到'time.Now() '因爲這個原因。它沒有克服它。爲什麼? – 2014-11-01 00:46:34

+0

問題是'time.Time'定義的'UnmarshalJSON'方法不知道如何處理'null'。你可能會爭辯說它應該是,但這是一個單獨的討論,並且可能值得發送一個錯誤報告。但現在它並不是,所以你需要管理它。上面的答案顯示了一種管理它的方法。 – dyoo 2014-11-01 00:58:02

+0

是的。我沒有爭論過。但現在我可以說它應該。我的觀點是,在我的'UnmarshalJSON'輸入中,這些字段不是'null',如下所示:'registerInstance = RegisterStructure {Timestamp:now,SignupTimestamp:now,} ' – 2014-11-01 01:00:12