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.NewEncoder
lugar 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/json
y 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-Type
esplain/text
al codificar.Content-Type
Primero debe configurar elw.Header().Set
código de respuesta HTTPw.WriteHeader
.Si llama
w.WriteHeader
primero, llamew.Header().Set
despué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
getJsonResponse
funció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.Data
puede 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 laResponseWriter
secuencia. 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