Pytanie: Obecnie drukuję moją odpowiedź w func Index
ten fmt.Fprintf(w, string(response))
sposób, jednak w jaki sposób mogę poprawnie wysłać JSON w żądaniu, aby mógł zostać wykorzystany przez widok?
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, "", " ")
}
Odpowiedzi:
Możesz ustawić nagłówek typu zawartości, aby klienci wiedzieli, że oczekują JSON
w.Header().Set("Content-Type", "application/json")
Innym sposobem organizowania struktury do json jest utworzenie kodera przy użyciu
http.ResponseWriter
// get a payload p := Payload{d} json.NewEncoder(w).Encode(p)
źródło
w.Header().Set("Content-Type", "application/json")
jest poprawny do ustawiania typu zawartości, nie działa, gdy używamjson.NewEncoder
zamiast tego otrzymuję wynik w formacie txt / zwykły. Czy ktoś inny to łapie. Odpowiedź z @poorva zadziałała zgodnie z oczekiwaniamiw.WriteHeader(http.StatusOk)
, otrzymuję powyższy wynik.w.WriteHeader(http.StatusOk)
użyjętext/plain; charset=utf-8
, otrzymam , jeśli nie ustawię jawnie kodu statusu, otrzymam,applicaton/json
a odpowiedź ma nadal kod stanu 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")
powyższejjson.NewEncoder(w).Encode(p)
pracy dla mnieInni użytkownicy komentując, że
Content-Type
jestplain/text
przy kodowaniu. Musisz ustawićContent-Type
pierwszyw.Header().Set
, a następnie kod odpowiedzi HTTPw.WriteHeader
.Jeśli zadzwonisz
w.WriteHeader
pierwszy, zadzwońw.Header().Set
po otrzymaniuplain/text
.Przykładowy program obsługi może wyglądać następująco;
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) }
źródło
Możesz zrobić coś takiego w swojej
getJsonResponse
funkcji -jData, err := json.Marshal(Data) if err != nil { // handle error } w.Header().Set("Content-Type", "application/json") w.Write(jData)
źródło
jData
prawdopodobnie niepotrzebnie używa ona segmentu bajtów .Data
może mieć dowolny rozmiar, w zależności od uporządkowanych danych, więc może to być nietrywialne marnotrawstwo pamięci. Po uporządkowaniu kopiujemy z pamięci doResponseWriter
strumienia. Odpowiedź, która używa json.NewEncoder () itp. Zapisze zorganizowany JSON bezpośrednio doResponseWriter
(do jego strumienia ..)Encoder.Encode()
funkcjiWe frameworku gobuffalo.io mam to tak, aby działało tak:
// 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")) }
a potem, gdy chcę uzyskać odpowiedź JSON dla tego zasobu, muszę ustawić „Content-type” na „application / json” i działa.
Myślę, że Railsy mają wygodniejszy sposób obsługi wielu typów odpowiedzi, nie widziałem tego samego w gobuffalo do tej pory.
źródło
Możesz użyć tego renderera pakietów , napisałem, aby rozwiązać tego rodzaju problem, jest to opakowanie obsługujące JSON, JSONP, XML, HTML itp.
źródło