Go lang解码io.read JSON v.s. unmarshal给出不同的结果

时间:2014-04-26 02:11:17

标签: json go

我有这样的处理程序:

type Location struct {
  Lat  float32 `json:"lat"`
  Lon  float32 `json:"lon"`
}



func handleJSONLocation(res http.ResponseWriter, req *http.Request) {    
    b := new(Location)
    var bb Location;
    buf := new(bytes.Buffer)
    buf.ReadFrom(req.Body)

    json.Unmarshal(buf.Bytes(), &bb)
    json.NewDecoder(req.Body).Decode(b)

    log.Printf("%s %f,%f %f,%f", buf.String(), b.Lat, b.Lon, bb.Lat, bb.Lon);

    data, _ := json.Marshal("{'location':'saved'}")
    res.Header().Set("Content-Type", "application/json; charset=utf-8")
    res.Write(data)
}

我得到了

2014/04/25 22:05:55 {"lat":42.9635013,"lon":-81.22387210000001} 0.000000,0.000000 42.963501,-81.223869

为什么b对象没有被解码?

此致

1 个答案:

答案 0 :(得分:8)

当您运行以下代码时,HTTP请求的整个主体将被读入buf

buf := new(bytes.Buffer)
buf.ReadFrom(req.Body)

此时,req.Body的进一步读取将导致EOF错误。因此,当您尝试解码为b时,您将收到一个错误,如果您使用以下内容检查返回值,则会显示错误:

if err := json.NewDecoder(req.Body).Decode(b); err != nil {
    log.Println("Could not decode body:", err)
}

检查你做的其他函数调用的错误也是明智的。

由于您已经将请求主体读入内存缓冲区,因此您可以创建一个新的bytes.Buffer来传递给期望io.Reader的API(例如json.NewDecoder)。