Search code examples
swiftswiftuialamofire

Decoding failed while fetching API | Swift


When I print self.getTokenBalancesModel it gives me the error that it failed Decoding. What am I doing wrong?

ViewModel

import Foundation
import Alamofire

final class TokenBalancesClassAViewModel: ObservableObject {
    
    @Published var getTokenBalancesModel: [GetTokenBalancesItemsModel] = [GetTokenBalancesItemsModel]()
    
    func makeApiRequest() {
        let url = "https://api.covalenthq.com/v1/1/address/0x726A73081C4134b2f639b821377482c71864EBc8/balances_v2/?&key=ckey_4eeea29a22c14701a9844f01151"
        
        AF.request(url).responseData(completionHandler: { data in
            if let apiJsonData = try? JSONDecoder().decode(TokenBalancesModel.self, from: data.data!){
                self.getTokenBalancesModel = apiJsonData.data.items
                print(self.getTokenBalancesModel)
            } else {
                print("Decoding failed")
            }
        })
    }
}

Models

struct TokenBalancesModel: Codable, Hashable {
    let data: TokenBalancesDataModel
    let error: Bool
}

struct TokenBalancesDataModel: Codable, Hashable {
    let address: String
    let quote_currency: String
    let items: [TokenBalancesItemsModel]
}

struct TokenBalancesItemsModel: Codable, Hashable {
    let contract_name: String
    let contract_ticker_symbol: String
//    let logo_url: String
    let balance: Int
    let quote_rate: Float
    let quote: Float
}

it's clearly in the decoding section:

if let apiJsonData = try? JSONDecoder().decode(TokenBalancesModel.self, from: data.data!){

where I'm making the mistake, but I don't see why


Solution

  • Instead try? you'll get more information if you catch the error.

    When debugging a common catch chain I'll use is

    } catch let DecodingError.dataCorrupted(context) {
        print(context)
    } catch let DecodingError.keyNotFound(key, context) {
        print("Key '\(key)' not found:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch let DecodingError.valueNotFound(value, context) {
        print("Value '\(value)' not found:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch let DecodingError.typeMismatch(type, context) {
        print("Type '\(type)' mismatch:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch {
        print("error: ", error)
    }
    

    By using the above you'll see the following error

    Type 'Int' mismatch: Expected to decode Int but found a string/data instead. codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "items", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "balance", intValue: nil)]

    Which will draw your attention to the TokenBalancesItemsModel.balance field being the incorrect type.