1

I've been trying to develop an app which fetches certain information of a book from Google Books API (name, author and image) and display the image inside a collection view

var bookInfo = [Book]()

let urlString = "https://www.googleapis.com/books/v1/volumes/J8ahqXjUhAAC"

    

override func awakeFromNib() {
    super.awakeFromNib()
    collectionView.delegate = self
    collectionView.dataSource = self
    
    let url = URL(string: urlString)
    
    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        do {
            self.bookInfo = try JSONDecoder().decode([Book].self, from: data!)
            for info in self.bookInfo {
                print(info.bookName)
            }
        }
        catch {
            print("error")
        }
    }
    
}

Below is a struct which represents the contents I'm trying to capture but not sure if this is entirely correct.

struct Book: Codable {
    var bookName: String
    var imageURL: String
    var pageCount: Int
    var author: String
    var format: String
}


struct volumeInfo: Codable {
    var bookInfo: [Book]
}

When running this code, I don't get any errors but the app is unable to fetch anything and my UIImageView is empty.

  • Missing `resume()`: `URLSession.shared.dataTask(with: url!) { (data, response, error) in ...}.resume()` – Larme May 21 '20 at 17:17
  • Next step: `print("error")` => `print("error: \(error)")`. You are missing the most important info when there is an error. – Larme May 21 '20 at 17:18
  • Thank you so much for your response! After doing so, I'm getting this error: error: typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil)) – Eashan Mathur May 21 '20 at 17:20
  • That means your JSON doesn't match your data structure. If you paste your json here: https://quicktype.io/ you get the correct structs to use in your app. – koen May 21 '20 at 17:21
  • First you JSON is a Dictionary at top level, not an array. That's the first issue. The rest, is that your structures don't match the JSON Structure at all. – Larme May 21 '20 at 17:23
  • So do I have to include every single var from my JSON into my struct? Even if i only want to access like the book image? – Eashan Mathur May 21 '20 at 17:27
  • You can avoid the adjacent keys that you don't use, but can't avoid the container keys. Eg: `volumeInfo` key is required if you need any of it's properties like `title`. And you can avoid `saleInfo` if you don't need it. – Frankenstein May 21 '20 at 17:30
  • So in terms of my JSON being a dictionary and not an array, what do I have to change/add to my code for that to be compatible? – Eashan Mathur May 21 '20 at 18:17

1 Answers1

0

The Book struct you are using wouldn't work because it doesn't match the JSON response. This is the entire struct but, you can remove keys(properties) that are not required and it would still work:

struct Book: Codable {
    let kind, id, etag, selfLink: String
    let volumeInfo: VolumeInfo
    let saleInfo: SaleInfo
    let accessInfo: AccessInfo
}

struct AccessInfo: Codable {
    let country, viewability: String
    let embeddable, publicDomain: Bool
    let textToSpeechPermission: String
    let epub, pdf: Epub
    let webReaderLink, accessViewStatus: String
    let quoteSharingAllowed: Bool
}

struct Epub: Codable {
    let isAvailable: Bool
}

struct SaleInfo: Codable {
    let country, saleability: String
    let isEbook: Bool
}

struct VolumeInfo: Codable {
    let title: String
    let authors: [String]
    let publisher, publishedDate, description: String
    let industryIdentifiers: [IndustryIdentifier]
    let readingModes: ReadingModes
    let pageCount, printedPageCount: Int
    let dimensions: Dimensions
    let printType: String
    let categories: [String]
    let averageRating: Double
    let ratingsCount: Int
    let maturityRating: String
    let allowAnonLogging: Bool
    let contentVersion: String
    let panelizationSummary: PanelizationSummary
    let imageLinks: ImageLinks
    let language, previewLink, infoLink, canonicalVolumeLink: String
}

struct Dimensions: Codable {
    let height, width, thickness: String
}

struct ImageLinks: Codable {
    let smallThumbnail, thumbnail: String
}

struct IndustryIdentifier: Codable {
    let type, identifier: String
}

struct PanelizationSummary: Codable {
    let containsEpubBubbles, containsImageBubbles: Bool
}

struct ReadingModes: Codable {
    let text, image: Bool
}
Frankenstein
  • 15,732
  • 4
  • 22
  • 47