How to serve up a JSON response using Go?

Question: Currently I'm printing out my response in the func Index like this fmt.Fprintf(w, string(response)) however, how can I send JSON properly in the request so that it maybe consumed by a view?

package main

import (
    "fmt"
    "github.com/julienschmidt/httprouter"
    "net/http"
    "log"
    "encoding/json"
)

type Payload struct {
    Stuff Data
}
type Data struct {
    Fruit Fruits
    Veggies Vegetables
}
type Fruits map[string]int
type Vegetables map[string]int


func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    response, err := getJsonResponse();
    if err != nil {
        panic(err)
    }
    fmt.Fprintf(w, string(response))
}


func main() {
    router := httprouter.New()
    router.GET("/", Index)
    log.Fatal(http.ListenAndServe(":8080", router))
}

func getJsonResponse()([]byte, error) {
    fruits := make(map[string]int)
    fruits["Apples"] = 25
    fruits["Oranges"] = 10

    vegetables := make(map[string]int)
    vegetables["Carrats"] = 10
    vegetables["Beets"] = 0

    d := Data{fruits, vegetables}
    p := Payload{d}

    return json.MarshalIndent(p, "", "  ")
}

Solution 1:

You can set your content-type header so clients know to expect json

w.Header().Set("Content-Type", "application/json")

Another way to marshal a struct to json is to build an encoder using the http.ResponseWriter

// get a payload p := Payload{d}
json.NewEncoder(w).Encode(p)

Solution 2:

Other users were commenting that the Content-Type is plain/text when encoding.
You have to set the content type with w.Header().Set() first, then write the HTTP response code with w.WriteHeader().

If you call w.WriteHeader() first, then call w.Header().Set() after you will get plain/text.

An example handler might look like this:

func SomeHandler(w http.ResponseWriter, r *http.Request) {
    data := SomeStruct{}
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(data)
}

Solution 3:

You can do something like this in you getJsonResponse function -

jData, err := json.Marshal(Data)
if err != nil {
    // handle error
}
w.Header().Set("Content-Type", "application/json")
w.Write(jData)