I would like to know how I could serve json response in a go server. This is what I am doing currently which throws an error in the browser(Mozilla) when I check for response.
Error message:- SyntaxError: JSON.parse unexpected end of line
This makes me believe the data part of response was not properly json encoded.
This is my Json response –
For the purpose of this forum I have altered the structure name and content. But it is pretty much the same.
I’m not sure it’s the root cause, but you’re setting the header twice and include a writeheader call between them. I’d remove the first header set and the writeheader to see what happens. Also, look at the output with something like curl -v to get more insight into what your server actually sends.
type Profile struct {
Name string
Hobbies []string
}
I am not able to use curl to test it as I am using this for FB login. The struct content which I am showing is not the exact one that I am using though. But basically I am trying to send a token back to the user for Facebook login. So can’t test with curl. This has to be the response on FB login. Can’t simulate exactly @calmh. But will try printing and testing it. Thanks a lot.
Hey @sandyethadka, after putting together a simple example using most of your code untouched, I am not receiving any errors in browser, lastly setting the content-type twice is slightly strange and also you should be making sure to check all errors, even from w.Write:
package main
import (
"encoding/json"
"log"
"net/http"
)
type Profile struct {
Name string
Hobbies []string
}
type JsonServer struct {
code int
}
func (j *JsonServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(j.code)
profile := Profile{"Alex", []string{"snowboarding", "programming"}}
js, err := json.Marshal(profile)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func main() {
http.Handle("/", &JsonServer{200})
log.Fatal(http.ListenAndServe(":9000", nil))
}
Hi @radovskyb
Will give this a try. Need to see what the issue really is. Setting twice might have created an issue? This code too sets it twice. Not sure what is the issue. Just to see if the header is written into I set the j.code for http.StatusFail to see the response in red(404) in the browser. So the traversal was not the issue. Will update here once I fix it. Thanks again…
Hi @radovskyb
Ya…Will check that out. Actually I am not sure which one is good when it comes to json, Marshal or Decoder…Is there any performance gains or anything between them?
Since you are writing directly to a writer I would personally use json.NewEncoder(w).Encode(...) instead of using json.Marshal(...), and only after marshalling data into JSON, writing to the writer.
My rule of thumb is that I use Encode when I’m writing directly to a writer, but use Marshal when I need to to something else with the bytes first before writing the JSON somewhere.
Just one more thing… If you are going to use a simple middleware like the JSON one I posted in my first example and you are going to encode many different types of data and serve them the same simple way, you could use something like this since it’s very clean:
package main
import (
"encoding/json"
"log"
"net/http"
)
type Profile struct {
Name string
Hobbies []string
}
type JsonServer struct {
data interface{}
code int
}
func (j *JsonServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(j.code)
if err := json.NewEncoder(w).Encode(&j.data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
profile := Profile{"Alex", []string{"snowboarding", "programming"}}
http.Handle("/", &JsonServer{data: &profile, code: http.StatusOK})
log.Fatal(http.ListenAndServe(":9000", nil))
}