dqkyz02602 2014-10-31 23:16
浏览 83
已采纳

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

I am trying to obtain an HTTP request body which is a json object and decode it into a Go struct I have defined.

Two of the fields of the struct is of time.Time type. While having only one such typed field everything works correctly.

If I have more than one time.Time typed fields in the go struct I cannot decode it and get the error:

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

The problem is in the decoding lines. Despite my debugging efforts I could have reached a meaningful result. That issue seems strange which is actually should not be.

What am I missing here?

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条回答 默认 最新

  • duanbing2963 2014-11-01 00:40
    关注

    Ok. Here is a reproducible example that demonstrates the error you're seeing.

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

    The error you're seeing has nothing to do with having multiple timestamps. This is why showing inputs is critical for debugging situations like this, and why you should go back and change your question to include a sample requestBody as part of the question content. Otherwise, it becomes very difficult to guess what you're doing.

    What's happening is that null is not handled by the JSON unmarshaller for time.Time. The documentation for time.Time's unmarshaller says: UnmarshalJSON implements the json.Unmarshaler interface. The time is expected to be a quoted string in RFC 3339 format.

    null is not such a value: the decoder in this case will not try to construct a "zero" value for the timestamp.

    What you want to do is change the type of SignupTimestamp from time.Time to *time.Time, so that the null value can be explicitly represented as a nil pointer.

    Here is an example to demonstrate:

    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
    ", registerInstance)
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大