'Go lang decode io.read JSON v.s. unmarshal giving different results
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
Solution 1:[1]
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
).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | James Henstridge |