2016-05-31 17 views
1

in JSON-Antwort verschachtelt ist Ich versuche, mit dem Flickr-API zu arbeiten, und ich habe einen Endpunkt, die mir eine Antwort wie dieseAbstellungs gibt mir nur die erste Element des Array, die

{ 
    "photos": { 
    "page": 1, 
    "pages": 500, 
    "perpage": 1, 
    "total": 500, 
    "photo": [ 
     { 
     "id": "12345", 
     "owner": "[email protected]", 
     "secret": "12ab345xyz", 
     "server": "1234", 
     "farm": 1, 
     "title": "Some Title", 
     "ispublic": 1, 
     "isfriend": 0, 
     "isfamily": 0 
     }, 
    ... 
    ] 
    }, 
    "stat": "ok" 
} 

ich eine Struktur haben gibt, dass sieht aus wie dieses

type FlickrResp struct { 
    Photos struct { 
     Page int   `json:"page"`  //what page the results were retreived from 
     Pages int   `json:"pages"`  //total number of pages of results 
     Perpage int   `json:"perpage"` //number of results per page 
     Total int   `json:"total"`  //total number of results 
     Photo []struct { 
      ID string  `json:"id"`   //image ID 
      Owner string `json:"owner"`  //owner ID 
      Secret string `json:"secret"`  //owner secret 
      Server string `json:"server"`  //server ID 
      Farm int  `json:"farm"`  //farm ID 
      Title string `json:"title"`  //image title 
      Ispublic string `json:"ispublic"` //is image publicly viewable? 
      Isfriend string `json:"isfriend"` //is image owner my friend? 
      Isfamily string `json:"isfamily"` //is image owner my family? 
     }     `json:"photo"`  //array of objects with details of photos 
    }      `json:"photos"`  //object that holds information about photoset 
    Stat string    `json:"stat"`  //status 
} 

und ich versuche, von a bis Abstellungs thusly

var fr FlickrResp            //create blank struct of type FlickrResp to hold JSON 
resp, err := ioutil.ReadAll(flickrCB.Body)      //read HTTP GET response 
if err != nil { 

} 
json.Unmarshal([]byte(resp), &fr)        //serialize JSON into template 

flickCB.Body kommt n http.Get

Das Problem ist, dass ich nur das erste Element des Foto-Array bekomme. Ich kann sehen, dass ich mehr als ein Element habe, wenn ich das Antwortobjekt als String ausdrucke. Was mache ich falsch? Ich habe mir schon seit ein paar Tagen den Kopf gegen Unmarshal und kompliziertere JSON-Antworten geschlagen.

+2

Liest du den Fehler von 'json.Unmarshal'? Wenn ich das obige versuche, bekomme ich ein Problem mit der Typabweichung zwischen 'ispublic', 'isfriend' und 'isfamily' im Vergleich zu den Strings, die die Struktur erwartet. Wenn ich die Typen ändere, scheint es in Ordnung zu sein. Hier ist ein Beispiel mit der Änderung, einschließlich der Verwendung für ein Feld von 'json.Number', was in solchen Fällen nützlich sein kann - https://play.golang.org/p/4fE_MkxgxS. Ich sehe zwei Einträge in 'Foto' in den Ergebnissen. – Bubbles

+0

Das ist es, danke. Ich möchte nicht darüber reden, wie oft ich darüber gegangen bin. –

Antwort

4

Beantwortet ursprünglich in den Kommentaren, aber für ein bisschen mehr Klarheit:

Es wurde eine nicht erfasste Fehler von json.Unmarshal:

json: cannot unmarshal number into Go value of type string

durch eine Art Konflikt zwischen der API Flimmern verursacht geben ispublic, isfriend und isfamily als Ganzzahlen, aber die Struktur erwartete Strings. Eine einfache Lösung besteht darin, sie in Ints zu konvertieren.

Eine andere Option für diese Art von Situationen ist die Verwendung json.Number, die eine grundlegende Zeichenfolge aus dem Quell-JSON umschließt und einige bequeme Methoden zur Verfügung stellt, um es später in eine Zahl umzuwandeln (oder einfach als String zu behalten). Durch sagen tun

Ispublic json.Number `json:"ispublic"` //is image publicly viewable? 
Isfriend json.Number `json:"isfriend"` //is image owner my friend? 
Isfamily json.Number `json:"isfamily"` 

Es wird funktionieren, und das Ergebnis leicht als String kann über fr.Ispublic.String() bekommen.

Eine ausführlichere Änderung, die in dieser Situation nützlich sein kann, ist die Verwendung eines benutzerdefinierten booleschen Typs. Die fraglichen Werte scheinen boolesche Werte zu spiegeln, aber ganze Zahlen werden auch booleschen Werten nicht zugeordnet. Ein benutzerdefinierter deserialisierter Typ kann verwendet werden. Angelehnt an this example an anderer Stelle auf Stackoverflow:

type ConvertibleBoolean bool 

func (bit ConvertibleBoolean) UnmarshalJSON(data []byte) error { 
    asString := string(data) 
    if asString == "1" || asString == "true" { 
     bit = true 
    } else if asString == "0" || asString == "false" { 
     bit = false 
    } else { 
     return errors.New(fmt.Sprintf("Boolean unmarshal error: invalid input %s", asString)) 
    } 
    return nil 
} 

Die obige Damit besteht die Möglichkeit Is* Werte als ConvertibleBoolean erklären, und die 0 & 1 Werte automatisch ordnen Sie vermutlich in diesen Bereichen von Flickr zu booleans bekommen würde.