I'm trying to display data from the Google Books API. The code behaves correctly with certain search queries but not with others. Below the search query is "weather," the console prints the correct JSON along with the "JSON failed to decode" message.
However, when I replace q=weather with q=hello I get the correct results displayed and the error message is not printed. My Response struct seems to be correct.
import SwiftUI
struct Response: Codable {
let kind: String
let totalItems: Int
let items: [Result]
}
struct Result: Codable, Identifiable {
var id: String
var etag: String
var selfLink: String
var volumeInfo: VolumeInfo
}
struct VolumeInfo: Codable {
let title: String
let authors: [String]
let publisher, publishedDate, description: String
let pageCount: Int
let imageLinks: ImageLinks
}
struct ImageLinks: Codable {
let thumbnail: String
}
struct IndustryIdentifier: Codable {
let type: TypeEnum
let identifier: String
}
enum TypeEnum: String, Codable {
case isbn10 = "ISBN_10"
case isbn13 = "ISBN_13"
}
struct BookSearchView: View {
@State private var results = [Result]()
var body: some View {
VStack {
List(results) { item in
HStack {
let baseURL = "https://books.google.com/books/content?id="
let bookID = item.id
let urlString = "\(baseURL)\. (bookID)&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
// put the url strings together with the bookID and convert to a URL object
let ImageURL = URL(string: urlString)
AsyncImage(url: ImageURL)
VStack(alignment: .leading) {
Text(item.volumeInfo.title)
.font(.headline)
Text("Authors: \(item.volumeInfo.authors.joined(separator: ", "))")
.font(.subheadline)
Divider()
Text("\(item.id)")
}
}
}
.task {
await loadData()
}
}
}
func loadData() async {
guard let url = URL(string: "https://www.googleapis.com/books/v1/volumes?q=weather") else {
print("Invalid URL")
return
}
do {
let (data, _) = try await URLSession.shared.data(from: url)
print("Received Data: \(String(data: data, encoding: .utf8) ?? "Data is empty")")
if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
results = decodedResponse.items
print("Results Count: \(results.count)")
} else {
print("JSON failed to decode")
}
} catch {
print("Error: \(error)")
}
}
}```
Read the API docs, and ensure that each optional property has a
?after it. For example try:and
Note, you will have to adjust
Text("Authors: ....