'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