Json Decode无法将json中的时间戳解析为Go结构

时间:2014-10-31 23:16:28

标签: json struct go

我正在尝试获取一个HTTP请求主体,它是一个json对象并将其解码为我定义的Go结构。

结构的两个字段是time.Time类型。虽然只有一个这样的类型字段,但一切正常。

如果我在go结构中有多个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)
}

1 个答案:

答案 0 :(得分: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 unmarshaller没有处理time.Timedocumentation为time.Time的unmarshaller说: UnmarshalJSON实现了json.Unmarshaler接口。预计时间是RFC 3339格式的带引号的字符串。

null不是这样的值:在这种情况下,解码器不会尝试为时间戳构造“零”值。

您要做的是将SignupTimestamp的类型从time.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)
    }
}