Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

json

go

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

like image 640
kthakore Avatar asked Sep 19 '25 00:09

kthakore


1 Answers

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

like image 64
James Henstridge Avatar answered Sep 20 '25 15:09

James Henstridge