Pergunta: Atualmente estou imprimindo minha resposta func Index
desta fmt.Fprintf(w, string(response))
forma, porém, como posso enviar JSON corretamente na solicitação para que seja consumido por uma visualização?
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, "", " ")
}
Respostas:
Você pode definir seu cabeçalho de tipo de conteúdo para que os clientes saibam o que esperar do json
w.Header().Set("Content-Type", "application/json")
Outra maneira de empacotar uma estrutura para json é construir um codificador usando o
http.ResponseWriter
// get a payload p := Payload{d} json.NewEncoder(w).Encode(p)
fonte
w.Header().Set("Content-Type", "application/json")
seja correto para definir o tipo de conteúdo, ele não faz quando uso emjson.NewEncoder
vez disso, eu obtenho um resultado txt / simples. Tem mais alguém pegando isso. A resposta de @poorva funcionou conforme o esperadow.WriteHeader(http.StatusOk)
, obtenho o resultado acima.w.WriteHeader(http.StatusOk)
então recebotext/plain; charset=utf-8
, se não definir o código de status explicitamente receboapplicaton/json
e a resposta ainda tem um código de status 200.Changing the header map after a call to WriteHeader (or Write) has no effect unless the modified headers are trailers.
w.Header().Set("Content-Type", "application/json")
acimajson.NewEncoder(w).Encode(p)
para mimOutros usuários comentando que
Content-Type
éplain/text
durante a codificação. Você deve definir oContent-Type
primeiro ew.Header().Set
, em seguida, o código de resposta HTTPw.WriteHeader
.Se você ligar
w.WriteHeader
primeiro, liguew.Header().Set
depois de receberplain/text
.Um exemplo de manipulador pode ser parecido com este;
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) }
fonte
Você pode fazer algo assim em sua
getJsonResponse
função -jData, err := json.Marshal(Data) if err != nil { // handle error } w.Header().Set("Content-Type", "application/json") w.Write(jData)
fonte
jData
, possivelmente desnecessariamente.Data
pode ser de tamanho arbitrário, dependendo dos dados que estão sendo organizados, portanto, isso pode ser um desperdício de memória não trivial. Após o marshalling, copiamos da memória para oResponseWriter
fluxo. A resposta que usa json.NewEncoder () etc. escreveria o JSON empacotado diretamente noResponseWriter
(em seu fluxo ..)Encoder.Encode()
funçãoNo framework gobuffalo.io, fiz funcionar assim:
// say we are in some resource Show action // some code is omitted user := &models.User{} if c.Request().Header.Get("Content-type") == "application/json" { return c.Render(200, r.JSON(user)) } else { // Make user available inside the html template c.Set("user", user) return c.Render(200, r.HTML("users/show.html")) }
e então, quando eu quiser obter uma resposta JSON para esse recurso, tenho que definir "Content-type" como "application / json" e funciona.
Acho que Rails tem uma maneira mais conveniente de lidar com vários tipos de resposta, não vi o mesmo no gobuffalo até agora.
fonte
Você pode usar este renderizador de pacote , eu escrevi para resolver este tipo de problema, é um wrapper para servir JSON, JSONP, XML, HTML etc.
fonte