2015-07-25 14 views
37

Domanda: Attualmente sto stampando la mia risposta nel func Index come questo fmt.Fprintf(w, string(response))però, come posso inviare JSON correttamente nella richiesta in modo che forse consumato da una vista?Come servire una risposta JSON usando Go?

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 può anche aiutare. – elithrar

risposta

60

È possibile impostare l'intestazione del tipo di contenuto in modo clienti sanno di aspettarsi JSON

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

Un altro modo per schierare una struct per JSON è quello di costruire un encoder utilizzando il http.ResponseWriter

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

Mentre 'w.Header(). Set (" Content-Type "," application/json ")' è corretto per l'impostazione del tipo di contenuto, non quando si usa 'json.NewEncoder' invece ottengo un txt/plain risultato. Qualcun altro sta ottenendo questo. La risposta di @poorva ha funzionato come previsto – Jaybeecave

+1

Scratch that. Se uso 'w.WriteHeader (http.StatusOk)' Ottengo il risultato sopra. – Jaybeecave

+1

Se uso 'w.WriteHeader (http.StatusOk)' allora ottengo 'text/plain; charset = utf-8', se non ho impostato esplicitamente il codice di stato ottengo 'applicaton/json' e la risposta ha ancora un codice di stato 200. –

10

Si può fare qualcosa di simile a voi nella funzione getJsonResponse -

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

Una nota importante su questa versione è che usa una porzione di byte in 'jData', forse inutilmente. 'Data' può essere di dimensione arbitraria, a seconda dei dati da sottoporre a marshalling, quindi questo potrebbe essere un waster di memoria non banale. Dopo il marshalling, copiamo dalla memoria al flusso di 'ResponseWriter'. La risposta che usa json.NewEncoder() ecc scriverebbe direttamente il JSON sottoposto a marshalling nel 'ResponseWriter' (nel suo stream ..) – Jonno

+1

ha funzionato per me! Affrontato il problema quando "w.WriteHeader (http.StatusCreated)" è stato aggiunto prima o dopo. – darkdefender27

+0

Non c'è bisogno di tornare dopo il panico in quanto esce dal programma – andersfylling

1

In gobuffalo.io quadro ho preso a lavorare in questo modo:

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

e poi quando voglio ottenere risposta JSON per quella risorsa devo impostare "Content-Type" a " application/json "e funziona.

Penso che Rails abbia un modo più conveniente di gestire più tipi di risposta, non ho visto lo stesso in gobuffalo finora.

6

Altri utenti hanno commentato che lo Content-Type è plain/text durante la codifica. Devi impostare prima w.Header().Set, quindi il codice di risposta HTTP con w.WriteHeader.

Se si chiama w.WriteHeader prima poi w.Header().Set otterrete 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

è possibile utilizzare questo package renderer, ho scritto per risolvere questo tipo di problema, è un wrapper per servire JSON, JSONP, XML, HTML ecc.

Problemi correlati