Search code examples
jsonswiftgoogle-books-api

No value associated with key CodingKeys error


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


Solution

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