Go语言解码`io.Read`的JSON与`unmarshal`给出不同的结果。

huangapple go评论90阅读模式
英文:

Go lang decode io.read JSON v.s. unmarshal giving different results

问题

我有一个像这样的处理程序:

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 对象没有被解码?

谢谢。

英文:

I have a handler like this:

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

I get

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

Why doesn't b object get decoded into?

Regards

答案1

得分: 10

当你运行以下代码时,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("无法解码主体:", err)
}

在其他函数调用时,检查错误也是明智的。

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

英文:

When you run the following code, the entire body of the HTTP request is read into buf:

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

At this point, further reads from req.Body will result in an EOF error. So when you attempt to decode into b, you are getting an error, which would be visible if you checked the return value with something like:

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

It would also be wise to check the error on the other function calls you make.

Since you've already read the request body into a memory buffer though, you could create a new bytes.Buffer to pass to APIs that expect an io.Reader (such as json.NewDecoder).

huangapple
  • 本文由 发表于 2014年4月26日 10:11:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/23305817.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定