2013-06-17 39 views
59

Web'den JSON verilerini okudum, ancak bu kod boş sonuç döndürüyor. Burada ne yapıyorum emin değilim.Golang'da JSON yanıtı nasıl alınır

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() 
} 

cevap

135

ideal bir şekilde ioutil.ReadAll kullanarak değil, doğrudan doğruya okuyucu üzerinde çözücü kullanımı değildir olup. İşte bir URL alan ve cevabını bir target yapısına çözen güzel bir işlev.

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

Örnek kullanım:

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

Bu cevap olarak üretimde http.Client yapı başlangıçta gösterdi * varsayılan kullanarak olmamalı! (Hangi http.Get/etc diyoruz). Nedeni, varsayılan istemcinin zaman aşımı yok olmasıdır; Uzak sunucu yanıt vermiyorsa, kötü bir gün geçireceksiniz.

+0

Bu çok yardımcı oldu. Hedefe ulaşmak biraz zamanımı aldı, ama yine de yeniyim. Bir yapıya son verdim, sonra '' 'tmp: = myStuct {}' '' '' '' 'json.NewDecoder (r.Body) .Decode (& tmp)' '' ve buradan jsonumu kullanabilirdim. – mvndaai

+4

Yapıdaki öğelerin adları için Uppercase'yi kullanmanız gerekiyor gibi görünüyor.'Tip WebKeys struct { \t Tuşlar [] struct { \t \t X5t dize \t \t -X5C [] dize \t} }' sen ayrıştırma ediyoruz JSON gerçek parametreler küçük harfle olduğunda bile. JSON örnek: '{ \t "anahtarlar": [{ \t \t "x5t": "fan", \t \t "-X5C": "baaaar" \t}] } 'doğru olduğundan – Wilson

+0

. Küçük harf tuşlarına, bildirildikleri paketin dışında erişilemez, "kodlama/json" bunları ayarlayamaz. –

10

Json paketleri tarafından kullanılmak üzere, yapılarınızda büyük harf özellik adlarına ihtiyacınız vardır.

Büyük harf özellik adları exported properties'dir. Küçük harf özellik adları dışa aktarılmaz.

Ayrıca, veri nesnesini başvuru kaynağına (&data) göndermeniz gerekir.

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

hala çalışmıyor, bu sizin için çalışıyor mu? Aynı boş yanıt – GOD

+1

"json paketlerinde kullanılmak üzere yapılarınızdaki büyük harf özellik adlarına ihtiyacınız var." – HVNSweeting

18

Kişisel Sorun (... Track için, onlar olmamalı hariç dilimleri) verilerinizin structs yılında dilim beyanları vardı. Bu, yapısal etiketler ile düzeltilebilen getirilen json dosyasında bazı oldukça goofy alan adları ile birleştirilmiştir, bkz. godoc.

Aşağıdaki kod, json'u başarıyla çözümledi. Başka sorularınız varsa, bana bildirin. json.Unmarshal (var data interface{} içine) den

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

Yanıt gövdesinde bir şey var. – peterSO

+4

Benim durumumda, "struct" alanlarında UPPER-CASE ilk karakterini kaçırıyordum. – abourget

+0

Aşağıya doğru cevap, doğrudan Decoder kullanarak bir Decoder kullanarak. Gereksiz tahsisleri önler ve genellikle daha ideomatik. Cevabımı düzeltdim, işaret ettiğin için teşekkürler. – tike

6

sonuç doğrudan Git tipi ve değişken bildirimleri uyuşmuyor. Örneğin,

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() 
} 

Çıkış:

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]]] 
İlgili konular