Вопрос: В настоящее время я распечатываю свой ответ func Index
таким образом, fmt.Fprintf(w, string(response))
однако, как я могу правильно отправить JSON в запросе, чтобы он мог быть использован представлением?
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, "", " ")
}
Ответы:
Вы можете установить заголовок типа содержимого, чтобы клиенты знали, что ожидать json
w.Header().Set("Content-Type", "application/json")
Другой способ маршалировать структуру в json - создать кодировщик с использованием
http.ResponseWriter
// get a payload p := Payload{d} json.NewEncoder(w).Encode(p)
источник
w.Header().Set("Content-Type", "application/json")
это правильно для установки типа контента, это не так, когдаjson.NewEncoder
вместо этого я получаю результат txt / plain. Кто-нибудь еще это понимает. Ответ от @poorva сработал, как ожидалосьw.WriteHeader(http.StatusOk)
я получаю вышеуказанный результат.w.WriteHeader(http.StatusOk)
то получаюtext/plain; charset=utf-8
, если я не устанавливаю код состояния явно, я получаю,applicaton/json
а в ответе все еще есть код состояния 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")
вышеупомянутойjson.NewEncoder(w).Encode(p)
работы для меняДругие пользователи комментируют, что
Content-Type
этоplain/text
при кодировании. Вы должны установитьContent-Type
сначалаw.Header().Set
, затем код ответа HTTPw.WriteHeader
.Если
w.WriteHeader
сначала позвоните, то позвонитеw.Header().Set
после того, как получитеplain/text
.Пример обработчика может выглядеть так;
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) }
источник
Вы можете сделать что-то подобное в своей
getJsonResponse
функции -jData, err := json.Marshal(Data) if err != nil { // handle error } w.Header().Set("Content-Type", "application/json") w.Write(jData)
источник
jData
, возможно, без необходимости.Data
может иметь произвольный размер, в зависимости от маршалируемых данных, поэтому это может быть нетривиальной потерей памяти. После маршаллинга мы копируем из памяти вResponseWriter
поток. Ответ, использующий json.NewEncoder () и т. Д., Запишет упорядоченный JSON прямо вResponseWriter
(в свой поток ..)Encoder.Encode()
функцииВ рамках gobuffalo.io я заставил его работать так:
// 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")) }
а затем, когда я хочу получить ответ JSON для этого ресурса, я должен установить «Content-type» на «application / json», и он работает.
Я думаю, что в Rails есть более удобный способ обработки нескольких типов ответов, я пока не видел такого в gobuffalo.
источник
Вы можете использовать этот рендерер пакетов , я написал для решения такого рода проблем, это оболочка для обслуживания JSON, JSONP, XML, HTML и т. Д.
источник