Pregunta: Actualmente estoy imprimiendo mi respuesta de func Index
esta fmt.Fprintf(w, string(response)) manera, sin embargo, ¿cómo puedo enviar JSON correctamente en la solicitud para que pueda consumirla una vista?
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, "", " ")
}

Respuestas:
Puede configurar su encabezado de tipo de contenido para que los clientes sepan que esperan json
w.Header().Set("Content-Type", "application/json")Otra forma de ordenar una estructura a json es construir un codificador usando el
http.ResponseWriter// get a payload p := Payload{d} json.NewEncoder(w).Encode(p)fuente
w.Header().Set("Content-Type", "application/json")es correcto para configurar el tipo de contenido, no lo hace cuando lo uso, en sujson.NewEncoderlugar obtengo un resultado txt / simple. ¿Alguien más está recibiendo esto? La respuesta de @poorva funcionó como se esperabaw.WriteHeader(http.StatusOk), obtengo el resultado anterior.w.WriteHeader(http.StatusOk), obtengotext/plain; charset=utf-8, si no configuro el código de estado explícitamente, obtengoapplicaton/jsony la respuesta todavía tiene un código de estado 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")anteriorjson.NewEncoder(w).Encode(p)para míOtros usuarios comentan que
Content-Typeesplain/textal codificar.Content-TypePrimero debe configurar elw.Header().Setcódigo de respuesta HTTPw.WriteHeader.Si llama
w.WriteHeaderprimero, llamew.Header().Setdespués de recibirplain/text.Un manejador de ejemplo podría verse así;
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) }fuente
Puedes hacer algo como esto en tu
getJsonResponsefunción:jData, err := json.Marshal(Data) if err != nil { // handle error } w.Header().Set("Content-Type", "application/json") w.Write(jData)fuente
jData, posiblemente innecesariamente.Datapuede ser de tamaño arbitrario, dependiendo de los datos que se están ordenando, por lo que esto podría ser un desperdicio de memoria no trivial. Después de la clasificación, copiamos de la memoria a laResponseWritersecuencia. La respuesta que usa json.NewEncoder (), etc.escribiría el JSON ordenado directamente enResponseWriter(en su flujo ..)Encoder.Encode()funciónEn el marco gobuffalo.io lo hice funcionar así:
// 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")) }y luego, cuando quiero obtener una respuesta JSON para ese recurso, tengo que configurar "Content-type" en "application / json" y funciona.
Creo que Rails tiene una forma más conveniente de manejar múltiples tipos de respuesta, no vi lo mismo en gobuffalo hasta ahora.
fuente
Puede usar este renderizador de paquetes , he escrito para resolver este tipo de problema, es un contenedor para servir JSON, JSONP, XML, HTML, etc.
fuente