SwiftUI API call to Airtable failing with JSON decoding issues

Hey everyone! I’m pretty new to Swift development and running into a frustrating issue while trying to pull data from Airtable’s API in my SwiftUI app.

I’ve got a basic table with movie names and images. Here’s what my API response looks like:

{
   "data":[
      {
         "recordId":"xyz123ABC",
         "timestamp":"2022-11-15T10:45:20.000Z",
         "attributes":{
            "name":"The Dark Knight",
            "poster":"darkKnightPoster"
         }
      },
      {
         "recordId":"def456GHI",
         "timestamp":"2022-11-15T10:45:21.000Z",
         "attributes":{
            "name":"Inception",
            "poster":"inceptionPoster"
         }
      }
   ]
}

I created this structure to decode the response:

struct APIResponse: Decodable {
    let data: [DataRecord]
    
    struct DataRecord: Decodable {
        let recordId: String
        let timestamp: String
        let attributes: MovieAttributes
    }
    
    struct MovieAttributes: Decodable {
        let name: String
        let poster: String
    }
}

And here’s my basic Movie model:

struct Movie: Identifiable {
    let id = UUID()
    let name: String
    let poster: String
}

My network call looks like this:

class MovieViewModel: ObservableObject {
    
    @Published var movies = [Movie]()
    
    func loadMovies() async {
        
        guard let endpoint = URL(string: "https://api.airtable.com/v0/appXYZ123/Movies") else {
            return
        }
        
        var apiRequest = URLRequest(url: endpoint)
        apiRequest.httpMethod = "GET"
        apiRequest.setValue(
            "Bearer my_api_token",
            forHTTPHeaderField: "Authorization"
        )
        
        let networkTask = URLSession.shared.dataTask(with: apiRequest) { responseData, httpResponse, requestError in
            
            if let requestError = requestError {
                print(requestError)
            } else if
                let responseData = responseData,
                let httpResponse = httpResponse as? HTTPURLResponse,
                httpResponse.statusCode == 200 {
                
                do {
                    let decodedResponse: APIResponse = try JSONDecoder().decode(APIResponse.self, from: responseData)
                    
                    DispatchQueue.main.async {
                        self.movies = []
                    }
                    
                    for dataRecord in decodedResponse.data {
                        DispatchQueue.main.async {
                            self.movies.append(
                                Movie(name: dataRecord.attributes.name, poster: String(dataRecord.attributes.poster))
                            )
                        }
                    }
                } catch {
                    print(error)
                }
            }
        }
        
        networkTask.resume()
    }
}

But I keep getting this decoding error:

keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "attributes", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"name\", intValue: nil) (\"name\").", underlyingError: nil))

I’ve been stuck on this for hours and tried different approaches but can’t figure out what’s wrong. Anyone have ideas what might be causing this?

your second record (index 1) is missing the ‘name’ field. add some debug prints to check the raw json response before decoding - you’ll probably find some records don’t have all the fields filled out.

The error’s hitting index 1 in your data array - one of your Airtable records has empty fields in the attributes object. Super common with Airtable since people leave cells blank all the time. Just make your MovieAttributes properties optional with question marks: let name: String? and let poster: String?. When you map to your Movie model, add default values or filter out incomplete records. I’ve hit this exact same issue - it’s always because someone didn’t fill out all the Airtable fields.

Your error’s happening at index 1 - your second record is missing the name field. Classic Airtable behavior - empty cells just disappear from the JSON response completely.

I hit this exact same issue last year building a content management system. You need to make your decode properties optional AND handle missing data properly.

Update your MovieAttributes struct:

struct MovieAttributes: Decodable {
    let name: String?
    let poster: String?
}

Then filter out incomplete records when creating Movie objects:

for dataRecord in decodedResponse.data {
    if let movieName = dataRecord.attributes.name,
       let moviePoster = dataRecord.attributes.poster {
        DispatchQueue.main.async {
            self.movies.append(Movie(name: movieName, poster: moviePoster))
        }
    }
}

This way you only add movies with both fields populated. Much cleaner than dealing with nil values in your UI later.