1

I'm trying to retrieve json from the google books api

Here are my structs:

struct Book: Codable {
    let volumeInfo: VolumeInfo
}

struct VolumeInfo: Codable {
    let title: String
    let authors: [String]
    let publisher, publishedDate, description: String
    
}

and this is the code to decode my json:

     var bookInfo = [Book]()

    override func viewDidLoad() {
        super.viewDidLoad()
        if let url = URL(string: "https://www.googleapis.com/books/v1/volumes?q=harry+potter") {

            URLSession.shared.dataTask(with: url) { data, response, error in
                if let data = data {
                    do {  
                        let parsedJSON = try JSONDecoder().decode(Book.self, from: data)
     
                        for books in self.bookInfo {
                            DispatchQueue.main.async {
                                print(books.volumeInfo.title)
                            }
                       }
                   } catch {
                       print(error)
                   }
               }
           }.resume()
            
        }       

}

and the error message I get is this:

keyNotFound(CodingKeys(stringValue: "volumeInfo", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "volumeInfo", intValue: nil) ("volumeInfo").", underlyingError: nil))

Jordan
  • 127
  • 1
  • 1
  • 9
  • 1
    You aren't parsing the first level before getting `Book` structure. See the JSON, you need first to access it through `"items"` key – Larme Jan 09 '22 at 20:09
  • 1
    Related: https://stackoverflow.com/questions/68690007/issue-with-json-decoding-how-can-i-debug-this/68690056#68690056 – vadian Jan 09 '22 at 20:20

1 Answers1

2

you are trying to decode a Book object, where you should be decoding the API response, then extract the Books from that. This is why you are getting the error.

Try the following example code:

struct Book: Identifiable, Codable {
    let id = UUID()
    let volumeInfo: VolumeInfo
}

struct VolumeInfo: Codable {
    let title, publishedDate: String
    let authors: [String]?
    let publisher, description: String?
    
}

struct ApiResponse: Codable {
    let kind: String
    let totalItems: Int
    let items: [Book]
}





var bookInfo = [Book]()

override func viewDidLoad() {
    super.viewDidLoad()
    if let url = URL(string: "https://www.googleapis.com/books/v1/volumes?q=harry+potter") {
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                do {
                    let response = try JSONDecoder().decode(ApiResponse.self, from: data)
                    bookInfo = response.items
                } catch {
                    print(error)
                }
            }
        }.resume()
    }
}