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

报告相同问题?

悬赏问题

  • ¥15 韩国网站购物,KG支付的支付回调如何解决
  • ¥15 workstation导入ovf文件,报错,怎么解决呢?
  • ¥15 关于#c语言#的问题:构成555单稳态触发器,采用LED指示灯延时时间,对延时时间进行测量并显示(如楼道声控延时灯)需要Proteus仿真图和C语言代码
  • ¥15 workstation加载centos进入emergency模式,查看日志报警如图,怎样解决呢?
  • ¥50 如何用单纯形法寻优不能精准找不到给定的参数,并联机构误差识别,给定误差有7个?matlab
  • ¥15 workstation加载centos进入emergency模式,查看日志报警如图,没有XFS,怎样解决呢?
  • ¥15 应用商店如何检测在架应用内容是否违规?
  • ¥15 Ubuntu系统配置PX4
  • ¥50 nw.js调用activex
  • ¥15 数据库获取信息反馈出错,直接查询了ref字段并且还使用了User文档的_id而不是自己的