2017-08-08 2 views
0

Also versuche ich Google Books API zu analysieren. Ich möchte Titel, Beschreibung, ThumbnailUrl, Autoren und veröffentlichte Daten erhalten. Hier ist das Problem:Google Books-API-Analyse

func getBooksFrom(completion: @escaping (Result<[[String: AnyObject]]>) -> Void) { 
    URLSession.shared.dataTask(with: url) { (data, response, error) in 
     guard error == nil else { return completion(.Error(error!.localizedDescription)) } 
     guard let data = data else { return 
      completion(.Error(error!.localizedDescription)) } 
     do { 
      if let json = try JSONSerialization.jsonObject(with: data, options: [.mutableContainers]) as? [String: AnyObject] { 
       if let items = json["items"] as? [[String: AnyObject]] { 
        DispatchQueue.main.async { 
         completion(.Succes(items)) 
        } 
       } 
      } 
     } catch let error { 
      print(error.localizedDescription) 
      return completion(.Error(error.localizedDescription)) 
     } 
    }.resume() 
} 

Und auf meinem View-Controller in der ViewDidLoad ich habe

let service = ApiService() 
    service.getBooksFrom { (result) in 
     switch result { 
     case .Succes(let data): 
      self.parseData(array: data) 
     case .Error(let message): 
      self.showAlertWith(title: "Error", and: message) 
     } 
    } 

Also das ist ziemlich einfach Parsing, aber ... Wenn ich Artikel in Buchobjekt zuordnen möchten i müssen:

func parseData(_ data: [[String: AnyObject]]) -> [Book]{ 
    for item in data { 
     if let volumeInfo = item["volumeInfo"] as? [String: AnyObject] { 
     let books = data.map { (jsonDictionary) -> Book in 
      let title = volumeInfo["title"] as? String ?? "" 
      let publishedData = volumeInfo["publishedDate"] as? String ?? "" 
      let authors = volumeInfo["authors"] as? [String] ?? [""] 

      let description = volumeInfo["description"] as? String ?? "" 
      let newBook = Book(title: title, publishedData: publishedData, description: description) 
      return newBook 
     } 
     return books 
     } 
    } 
    return [Book]() 
} 

die super schreckliche Art und Weise ist, es zu tun .. Sie haben auf dem Boden Buch zurück, wegen des for-Schleife, und VolumeInfo nächster Dic ist näre, ich weiß also wirklich nicht genau, wie es zur Karte und zum Beispiel Autoren bekommen, weil es .. nächster Array ist

Eine Probe JSON-Objekt:

{ 
    "items":[ 
     { 
     "volumeInfo":{ 
      "title":"The Ancestor's Tale", 
      "subtitle":"A Pilgrimage to the Dawn of Life", 
      "authors":[ 
       "Richard Dawkins", 
       "Yan Wong" 
      ] 
      "publishedDate":"2016-04-28", 
      "description":"A fully updated ", 
      "imageLinks":{ 
       "smallThumbnail":"http://books.google.com/books/content?id=vzbVCQAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api", 
       "thumbnail":"http://books.google.com/books/content?id=vzbVCQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api" 
      } 
}  
]} 

Also das ist ganz einfach, wenn Sie Array von String: Wert, aber wie sollten Sie in der richtigen Weise zuordnen, wenn Sie zum Beispiel Wörterbücher im Dictionary VolumeInfo oder Array von Strings wie Autoren haben?

+0

'Autoren' ist ein Array von String, kein Wörterbuch. – Larme

+0

@Larme ja, du hast Recht :) – Magnifique

+0

Bearbeite deine Frage mit dem JSON-Beispiel anstatt eines Links im Kommentar, der nützlich sein könnte ... Beachte, dass die 'volumeInfo [" description "] als? Schnur ?? "" alle Thesen "?" Tests könnten stattdessen in der "init" -Methode von Book durchgeführt werden, und hier eine klarere Analyse machen. – Larme

Antwort

1

Ich persönlich finde den Weg, Objekte in Swift mit URLSession relativ ungeschickt zu analysieren. Wann immer ich kann ich Alamofire in Kombination mit der AlamofireObjectMapper verwenden.

Damit können Sie ein einfaches Objekt erstellen. Zum Beispiel:

class Book: Mappable { 
     var title: String? 
     var subtitle: String? 
     var description: String? 

     required init?(map: Map){ 

     } 

     func mapping(map: Map) { 
     title <- map["title"] 
     subtitle <- map["subtitle"] 
     description <- map["description"] 
     } 
} 

Wenn Sie eine Anfrage machen, können Sie dann die responseObject Methode verwenden, um direkt das Objekt zu analysieren und die richtigen Typen zuordnen.

Alamofire.request(URL).responseObject { (response: DataResponse<Book>) in 
    let book = response.result.value 
    print(book?.title) 
} 

Für dieses Beispiel habe ich einfach nur ein Buch geparst. Aber das Konzept kann auch leicht auf Arrays oder verschachtelte JSON-Objekte erweitert werden. Ich persönlich finde das führt zu viel sauberer Code als URLSession direkt zu verwenden.

+0

Vielen Dank, es hat geklappt! <3 In dieser typischen JSON-Antwort müssen Sie reponseArray und kayPath verwenden, aber alles funktioniert perfekt und es ist viel einfacher! :) – Magnifique

+0

Froh ich könnte helfen :) –