kthakore
kthakore

Reputation: 1604

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

Upvotes: 4

Views: 6684

Answers (1)

James Henstridge
James Henstridge

Reputation: 43949

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

Upvotes: 10

Related Questions