2015-07-25 4 views
37

Frage: meine Antwort Derzeit in den func Index wie diese fmt.Fprintf(w, string(response))aber ich drucke aus, wie kann ich JSON richtig in der Anforderung senden, so dass es vielleicht eine Ansicht verbraucht?Wie wird eine JSON-Antwort mit Go bereitgestellt?

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, "", " ") 
} 
+0

https://github.com/unrolled/render kann auch helfen. – elithrar

Antwort

60

Sie können Ihre Content-Type-Header gesetzt, damit Kunden json

w.Header().Set("Content-Type", "application/json")

Eine weitere Möglichkeit, eine Struktur Marschall zu json einen Encoder zu bauen, ist mit dem http.ResponseWriter

zu erwarten wissen
// get a payload p := Payload{d} 
json.NewEncoder(w).Encode(p) 
+3

Während 'w.Header(). Set (" Content-Type "," application/json ")' ist richtig für die Einstellung des Inhaltstyps, es nicht bei der Verwendung von 'json.NewEncoder' stattdessen bekomme ich eine TXT/plain Ergebnis. Ist das jemand anderes? Die Antwort von @poorva hat wie erwartet funktioniert – Jaybeecave

+1

Scratch das. Wenn ich 'w.WriteHeader (http.StatusOk)' verwende, bekomme ich das obige Ergebnis. – Jaybeecave

+1

Wenn ich 'w.WriteHeader (http.StatusOk)' verwende, dann bekomme ich 'text/plain; charset = utf-8', wenn ich den Status-Code nicht explizit setze, bekomme ich 'application/json' und die Response hat noch einen Status-Code 200. –

10

Sie können so etwas in Ihnen tun getJsonResponse Funktion -

jData, err := json.Marshal(Data) 
if err != nil { 
    panic(err) 
    return 
} 
w.Header().Set("Content-Type", "application/json") 
w.Write(jData) 
+2

Eine wichtige Anmerkung zu dieser Version ist, dass sie eine Byte-Scheibe in 'jData' verwendet, möglicherweise unnötig. 'Daten' können von beliebiger Größe sein, abhängig von den Daten, die gemarshallt werden, also könnte dies ein nicht trivialer Speicherverschwender sein. Nach dem Marshalling kopieren wir aus dem Speicher in den Stream 'ResponseWriter'. Die Antwort, die json.NewEncoder() usw. verwendet, würde den Marshalling-JSON direkt in den ResponseWriter (in seinen Stream) schreiben.) – Jonno

+1

Arbeitete für mich! Konfrontiert mit dem Problem, wenn 'w.WriteHeader (http.StatusCreated)' vorher oder nachher hinzugefügt wurde. – darkdefender27

+0

Keine Notwendigkeit, nach Panik zurückzukehren, da dies Ihr Programm beendet – andersfylling

1

In gobuffalo.io Rahmen habe ich es so arbeiten:

// 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")) 
} 

und dann, wenn ich will für diese Ressource JSON Antwort erhalten Ich habe „Content-Type“ auf "einstellen Anwendung/JSON "und es funktioniert.

Ich denke, Rails hat eine bequemere Möglichkeit, mehrere Antworttypen zu behandeln, ich sah nicht das gleiche in gobuffalo so weit.

6

Andere Benutzer kommentieren, dass die Content-Typeplain/text bei der Codierung ist. Sie müssen die zuerst w.Header().Set, dann den HTTP-Antwortcode mit w.WriteHeader setzen.

Wenn Sie w.WriteHeader zuerst rufen dann w.Header().Set Sie 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) 
} 
0

bekommen Sie diesen package renderer verwenden können, habe ich geschrieben, diese Art von Problem zu lösen, ist es ein Wrapper JSON zu dienen, JSONP, XML, HTML usw.

Verwandte Themen