英文:
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
).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论