गो का उपयोग करके JSON प्रतिक्रिया कैसे प्रदान करें?


97

प्रश्न: वर्तमान में मैं 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, "", "  ")
}

github.com/unrolled/render भी मदद कर सकता है।
एलीथ्रर

जवाबों:


130

आप अपना कंटेंट-टाइप हेडर सेट कर सकते हैं ताकि क्लाइंट्स को json की उम्मीद हो

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

JSON के लिए एक संरचना को मार्शल करने के लिए एक और तरीका एक एनकोडर का उपयोग करके बनाना है http.ResponseWriter

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

11
जबकि w.Header().Set("Content-Type", "application/json")सामग्री प्रकार की स्थापना के लिए सही है, तो यह उपयोग करते समय नहीं है json.NewEncoderबजाय मैं एक txt / सादे परिणाम मिलता है। किसी और को यह हो रही है @Poorva के जवाब ने उम्मीद के मुताबिक काम किया
Jaybeecave

2
उसको खरोंचो। यदि मैं उपयोग करता w.WriteHeader(http.StatusOk) हूं तो मुझे उपरोक्त परिणाम मिलता है।
जयबेकेव

4
अगर मैं उपयोग करता हूं w.WriteHeader(http.StatusOk)तो मुझे मिलता है text/plain; charset=utf-8, अगर मुझे स्टेटस-कोड स्पष्ट रूप से नहीं मिलता है applicaton/jsonऔर मुझे रिस्पॉन्स अभी भी स्टेटस-कोड 200 है।
रेमन रेम्बो

1
हम्म् ... यहाँ डॉक्स के साथ क्या करना पड़ सकता है ? Changing the header map after a call to WriteHeader (or Write) has no effect unless the modified headers are trailers.
दान एस्परज़ा

2
मेरे लिए w.Header().Set("Content-Type", "application/json")उपरोक्त json.NewEncoder(w).Encode(p)कार्य जोड़ना
अरड़ी नुसावन

35

अन्य उपयोगकर्ताओं को टिप्पणी की कि Content-Typeहै plain/textजब एन्कोडिंग। आपको Content-Typeपहले w.Header().Set, फिर HTTP प्रतिक्रिया कोड सेट करना होगा w.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)
}

प्रतिक्रिया कैसे लौटाएं, यदि मेरा कार्यक्रम आतंकित करता है? मैंने ठीक होने () का उपयोग करने की कोशिश की, फिर उनके पास से लौट आया लेकिन यह काम नहीं किया।
infiniteLearner

28

आप कुछ इस तरह से getJsonResponseकार्य कर सकते हैं -

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

2
इस संस्करण के बारे में एक महत्वपूर्ण बात यह है कि यह एक बाइट स्लाइस का उपयोग करता है jData, संभवतः अनावश्यक रूप से। Dataडेटा आकार के आधार पर, मनमाने आकार का हो सकता है, इसलिए यह एक गैर-तुच्छ मेमोरी वास्टर हो सकता है। मार्शलिंग के बाद, हम मेमोरी से ResponseWriterस्ट्रीम में कॉपी करते हैं। वह उत्तर जो json.NewEncoder () आदि का उपयोग करता है, मार्शेल्ड JSON को सीधे ResponseWriter(इसकी स्ट्रीम में ..)
लिखेगा

1
मेरे लिए काम किया! 'W.WriteHeader (http.StatusCreated)' समस्या को पहले या बाद में जोड़ा गया था।
darkdefender27

1
इस के रूप में आतंक के बाद वापसी करने के लिए कोई ज़रूरत नहीं अपने कार्यक्रम बाहर निकालता है
andersfylling

कम से कम यह समाधान Encoder.Encode()फ़ंक्शन के ट्रेलिंग \ n को नहीं जोड़ता है
जोनाथन मुलर

2

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 प्रतिक्रिया प्राप्त करना चाहता हूं तो मुझे "एप्लिकेशन / जसन" के लिए "सामग्री-प्रकार" सेट करना होगा और यह काम करेगा।

मुझे लगता है कि रेल के पास कई प्रतिक्रिया प्रकारों को संभालने के लिए अधिक सुविधाजनक तरीका है, मैंने अब तक गोबफलो में समान नहीं देखा था।


0

आप इस पैकेज रेंडरर का उपयोग कर सकते हैं , मैंने इस तरह की समस्या को हल करने के लिए लिखा है, यह JSON, JSONP, XML, HTML आदि की सेवा करने के लिए एक आवरण है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.