কীভাবে http.Get থেকে JSON প্রতিক্রিয়া পাবেন


135

আমি ওয়েব থেকে জেএসএন ডেটা পড়ার চেষ্টা করছি, তবে সেই কোডটি খালি ফলাফল দেয়। আমি নিশ্চিত না যে আমি এখানে কী ভুল করছি।

package main

import "os"
import "fmt"
import "net/http"
import "io/ioutil"
import "encoding/json"

type Tracks struct {
    Toptracks []Toptracks_info
}

type Toptracks_info struct {
    Track []Track_info
    Attr  []Attr_info
}

type Track_info struct {
    Name       string
    Duration   string
    Listeners  string
    Mbid       string
    Url        string
    Streamable []Streamable_info
    Artist     []Artist_info
    Attr       []Track_attr_info
}

type Attr_info struct {
    Country    string
    Page       string
    PerPage    string
    TotalPages string
    Total      string
}

type Streamable_info struct {
    Text      string
    Fulltrack string
}

type Artist_info struct {
    Name string
    Mbid string
    Url  string
}

type Track_attr_info struct {
    Rank string
}

func get_content() {
    // json data
    url := "http://ws.audioscrobbler.com/2.0/?method=geo.gettoptracks&api_key=c1572082105bd40d247836b5c1819623&format=json&country=Netherlands"

    res, err := http.Get(url)

    if err != nil {
        panic(err.Error())
    }

    body, err := ioutil.ReadAll(res.Body)

    if err != nil {
        panic(err.Error())
    }

    var data Tracks
    json.Unmarshal(body, &data)
    fmt.Printf("Results: %v\n", data)
    os.Exit(0)
}

func main() {
    get_content()
}

উত্তর:


266

আদর্শ উপায়টি ব্যবহার না করে ioutil.ReadAllবরং সরাসরি পাঠকের উপরে একটি ডিকোডার ব্যবহার করুন। এখানে একটি দুর্দান্ত ফাংশন যা একটি url পায় এবং তার প্রতিক্রিয়াটি কোনও targetকাঠামোর উপরে ডিকোড করে ।

var myClient = &http.Client{Timeout: 10 * time.Second}

func getJson(url string, target interface{}) error {
    r, err := myClient.Get(url)
    if err != nil {
        return err
    }
    defer r.Body.Close()

    return json.NewDecoder(r.Body).Decode(target)
}

উদাহরণ ব্যবহার:

type Foo struct {
    Bar string
}

func main() {
    foo1 := new(Foo) // or &Foo{}
    getJson("http://example.com", foo1)
    println(foo1.Bar)

    // alternately:

    foo2 := Foo{}
    getJson("http://example.com", &foo2)
    println(foo2.Bar)
}

*http.Clientএই উত্তরটি মূলত প্রদর্শিত হিসাবে আপনি উত্পাদনে ডিফল্ট কাঠামোটি ব্যবহার করবেন না ! (কোনটি http.Get/ ইত্যাদি কল করে)। কারণটি হ'ল ডিফল্ট ক্লায়েন্টের কোনও টাইমআউট সেট নেই; যদি রিমোট সার্ভারটি প্রতিক্রিয়াবিহীন হয় তবে আপনার খুব খারাপ দিন যাবে।


5
দেখে মনে হচ্ছে আপনার স্ট্রাক্টের আইটেমগুলির নামের জন্য বড় হাতের অক্ষর ব্যবহার করা দরকার যেমন আপনি type WebKeys struct { Keys []struct { X5t string X5c []string } } যখন JSON পার্স করছেন তখন প্রকৃত প্যারামগুলি নিম্ন ক্ষেত্রে রয়েছে। জেএসন উদাহরণ:{ "keys": [{ "x5t": "foo", "x5c": "baaaar" }] }
উইলসন

1
@ রোমান, না যদি কোনও ত্রুটি ফিরে আসে তবে প্রতিক্রিয়া মানটি শূন্য। (একটি ত্রুটি মানে আমরা কোনও বৈধ এইচটিটিপি প্রতিক্রিয়া পড়তে পারি নি, বন্ধ করার মতো কোনও শরীর নেই!) আপনি এটি পরীক্ষা করে পরীক্ষা করতে পারেন। অস্তিত্বহীন URL এ যান () যান। নেট / http ডক্সে দ্বিতীয় কোড ব্লকে টিআইএস পদ্ধতিটি প্রদর্শিত হয় ।
কনার পিট

1
@ নামজিভিউ একটি সম্ভাব্য বরাদ্দ সংরক্ষণ করে এবং সংযুক্তি পুনরায় ব্যবহার করতে HTTP- র ব্যবহারের অনুমতি দেয়।
কনার পিট

2
@ কনরপীট আপনি আমার দিনকে ধন্যবাদ জানিয়েছেন! "আপনারা ডিফল্ট * HTTP ব্যবহার না করা উচিত C আপনি কি বোঝাতে চেয়েছেন যে &http.Client{Timeout: 10 * time.Second}কোনও একটি সম্পূর্ণ অন্যান্য গ্রন্থাগার / কৌশল ব্যবহার করা উচিত ?
জোনা রডরিগস

6
অন্যকে কেবল একটি সতর্কতা - নির্দিষ্ট ধরণের ত্রুটিযুক্ত JSON এর জন্য কোনও ত্রুটি ফিরিয়ে json.NewDecoder(r.Body).Decode(target)দেবে না ! আমি কেন খালি সাড়া পেয়েছি তা বোঝার চেষ্টা করে কয়েক ঘন্টা নষ্ট করেছি - উত্সটি দেখা গেছে জেএসওনের একটি অতিরিক্ত কমা ছিল যেখানে এটি হওয়া উচিত ছিল না। আমি আপনাকে json.Unmarshalপরিবর্তে ব্যবহার করার পরামর্শ দিচ্ছি । এছাড়া ব্যবহারের অন্যান্য সম্ভাব্য বিপদ সম্পর্কে একটি ভালো কাজের মধ্যে থাকবেন এর json.Decoder এখানে
adamc

25

আপনার সমস্যাটি ছিল আপনার ডেটাগুলিতে স্লাইস ডিক্লেয়ারেশন structs(বাদে Trackসেগুলি টুকরো টুকরো টানা উচিত নয় ...)। এটি আনীত জেএসন ফাইলের কিছু মূর্খ ফিল্ডনেম দ্বারা সংমিশ্রিত করা হয়েছিল, যা স্ট্রাকট্যাগগুলির মাধ্যমে স্থির করা যায়, গডোক দেখুন

নীচের কোডটি জাসনকে সফলভাবে পার্স করেছে। যদি আপনার আরও প্রশ্ন থাকে তবে আমাকে জানান।

package main

import "fmt"
import "net/http"
import "io/ioutil"
import "encoding/json"

type Tracks struct {
    Toptracks Toptracks_info
}

type Toptracks_info struct {
    Track []Track_info
    Attr  Attr_info `json: "@attr"`
}

type Track_info struct {
    Name       string
    Duration   string
    Listeners  string
    Mbid       string
    Url        string
    Streamable Streamable_info
    Artist     Artist_info   
    Attr       Track_attr_info `json: "@attr"`
}

type Attr_info struct {
    Country    string
    Page       string
    PerPage    string
    TotalPages string
    Total      string
}

type Streamable_info struct {
    Text      string `json: "#text"`
    Fulltrack string
}

type Artist_info struct {
    Name string
    Mbid string
    Url  string
}

type Track_attr_info struct {
    Rank string
}

func perror(err error) {
    if err != nil {
        panic(err)
    }
}

func get_content() {
    url := "http://ws.audioscrobbler.com/2.0/?method=geo.gettoptracks&api_key=c1572082105bd40d247836b5c1819623&format=json&country=Netherlands"

    res, err := http.Get(url)
    perror(err)
    defer res.Body.Close()

    decoder := json.NewDecoder(res.Body)
    var data Tracks
    err = decoder.Decode(&data)
    if err != nil {
        fmt.Printf("%T\n%s\n%#v\n",err, err, err)
        switch v := err.(type){
            case *json.SyntaxError:
                fmt.Println(string(body[v.Offset-40:v.Offset]))
        }
    }
    for i, track := range data.Toptracks.Track{
        fmt.Printf("%d: %s %s\n", i, track.Artist.Name, track.Name)
    }
}

func main() {
    get_content()
}

1
প্রতিক্রিয়া বডি কিছু আছে।
পিটারসো

6
আমার ক্ষেত্রে, আমি "কাঠামো" ক্ষেত্রগুলির মধ্যে UPPER-CASE প্রথম অক্ষরটি অনুপস্থিত।
গর্ভাজা

নীচে উত্তরটি সঠিক, প্রতিক্রিয়াটিতে সরাসরি একটি ডিকোডার ব্যবহার করে ody রক্তাক্ত অপ্রয়োজনীয় বরাদ্দগুলি এড়িয়ে চলে এবং সাধারণত আদর্শ হয়। আমার উত্তরটি সংশোধন করে, এটিকে নির্দেশ করার জন্য ধন্যবাদ।
12:30

ওবাগেট ওএমজি এই মন্তব্যের জন্য আপনাকে ধন্যবাদ। পার্সারে সমস্যাগুলি অনুসন্ধানের জন্য কেবল 1 ঘন্টা ব্যয় করুন,
ওয়্যারশার্ক

14

জেসন প্যাকেজগুলি ব্যবহার করার জন্য আপনার স্ট্রাক্টগুলিতে আপনার উচ্চ স্তরের সম্পত্তির নাম প্রয়োজন।

আপার কেস প্রোপার্টি নাম exported properties। লোয়ার কেস প্রোপার্টি নাম রফতানি হয় না।

আপনার ডেটা অবজেক্টটি রেফারেন্স ( &data) দ্বারা পাস করতে হবে ।

package main

import "os"
import "fmt"
import "net/http"
import "io/ioutil"
import "encoding/json"

type tracks struct {
    Toptracks []toptracks_info
}

type toptracks_info struct {
    Track []track_info
    Attr  []attr_info
}

type track_info struct {
    Name       string
    Duration   string
    Listeners  string
    Mbid       string
    Url        string
    Streamable []streamable_info
    Artist     []artist_info
    Attr       []track_attr_info
}

type attr_info struct {
    Country    string
    Page       string
    PerPage    string
    TotalPages string
    Total      string
}

type streamable_info struct {
    Text      string
    Fulltrack string
}

type artist_info struct {
    Name string
    Mbid string
    Url  string
}

type track_attr_info struct {
    Rank string
}

func get_content() {
    // json data
    url := "http://ws.audioscrobbler.com/2.0/?method=geo.gettoptracks&api_key=c1572082105bd40d247836b5c1819623&format=json&country=Netherlands"

    res, err := http.Get(url)

    if err != nil {
        panic(err.Error())
    }

    body, err := ioutil.ReadAll(res.Body)

    if err != nil {
        panic(err.Error())
    }

    var data tracks
    json.Unmarshal(body, &data)
    fmt.Printf("Results: %v\n", data)
    os.Exit(0)
}

func main() {
    get_content()
}

এখনও কাজ করে না, এটি কি আপনার জন্য কাজ করছে? একই ফাঁকা প্রতিক্রিয়া
অক্ষয়দীপ গিরি

3
"জেএসন প্যাকেজগুলি ব্যবহার করার জন্য আপনার স্ট্রাক্টগুলিতে আপনার উচ্চ স্তরের সম্পত্তির নাম প্রয়োজন for" ধন্যবাদ
এইচভিএনএসইয়েটিং

8

json.Unmarshal(এর মধ্যে var data interface{}) থেকে প্রাপ্ত ফলাফলগুলি আপনার গো প্রকার এবং পরিবর্তনশীল ঘোষণার সাথে সরাসরি মেলে না। উদাহরণ স্বরূপ,

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
)

type Tracks struct {
    Toptracks []Toptracks_info
}

type Toptracks_info struct {
    Track []Track_info
    Attr  []Attr_info
}

type Track_info struct {
    Name       string
    Duration   string
    Listeners  string
    Mbid       string
    Url        string
    Streamable []Streamable_info
    Artist     []Artist_info
    Attr       []Track_attr_info
}

type Attr_info struct {
    Country    string
    Page       string
    PerPage    string
    TotalPages string
    Total      string
}

type Streamable_info struct {
    Text      string
    Fulltrack string
}

type Artist_info struct {
    Name string
    Mbid string
    Url  string
}

type Track_attr_info struct {
    Rank string
}

func get_content() {
    // json data
    url := "http://ws.audioscrobbler.com/2.0/?method=geo.gettoptracks&api_key=c1572082105bd40d247836b5c1819623&format=json&country=Netherlands"
    url += "&limit=1" // limit data for testing
    res, err := http.Get(url)
    if err != nil {
        panic(err.Error())
    }
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        panic(err.Error())
    }
    var data interface{} // TopTracks
    err = json.Unmarshal(body, &data)
    if err != nil {
        panic(err.Error())
    }
    fmt.Printf("Results: %v\n", data)
    os.Exit(0)
}

func main() {
    get_content()
}

আউটপুট:

Results: map[toptracks:map[track:map[name:Get Lucky (feat. Pharrell Williams) listeners:1863 url:http://www.last.fm/music/Daft+Punk/_/Get+Lucky+(feat.+Pharrell+Williams) artist:map[name:Daft Punk mbid:056e4f3e-d505-4dad-8ec1-d04f521cbb56 url:http://www.last.fm/music/Daft+Punk] image:[map[#text:http://userserve-ak.last.fm/serve/34s/88137413.png size:small] map[#text:http://userserve-ak.last.fm/serve/64s/88137413.png size:medium] map[#text:http://userserve-ak.last.fm/serve/126/88137413.png size:large] map[#text:http://userserve-ak.last.fm/serve/300x300/88137413.png size:extralarge]] @attr:map[rank:1] duration:369 mbid: streamable:map[#text:1 fulltrack:0]] @attr:map[country:Netherlands page:1 perPage:1 totalPages:500 total:500]]]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.